【Swift】カスタムViewとViewControllerの作成

# はじめに
xibを使って、レイアウトはViewに、イベントはViewControllerで処理する場合のシンプルな実装方法を紹介します。
# ゴール（完成図）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/efb2e044-d7c7-9082-a2e4-6e1a1f9dd5ad.png" width=40%>


xibを使って、ViewControllerにカスタムViewを表示させる。
※青背景色の部分がUIViewController、白背景色の部分がUIView。
おおまかな開発の流れとしては、ViewControllerにViewを埋め込む感じです。

# 1.カスタムUIView、UIViewControllerのswiftファイルと、それに紐付くxibファイルの作成
- UIViewはSwiftとViewファイル別々に選択して作成する必要があり、UIViewControllerはcocoaTouchClassでxibファイルを一気に作成することができます。
 ※Viewのxibファイルを作成する際は、File→New File→でccoa touch classで選択してAlso createXIB fileが選択できないので注意。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/ac834519-cf76-c196-11d4-8711537ffd7f.png" width=30%>

- xibファイルの作成は、File →NewFile　→Viewを選択

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/8e03277d-cc7f-2dd5-5b75-fdfa86a7c48a.png" width=30%>

- Swiftファイルの作成はFile →NewFile→Swiftを選択


- ViewControllerについてはまとめてxibファイルを作成
File→NewFile→CocoaTouchClassを選択でSubClass of:をUIViewControllerに指定し、Also Create XibFileにチェック→Next→Createを選択。
今回のファイル名はContentViewにします。
↓こんな感じでそれぞれxibとswiftファイルを作成できていたらOKです。
 ![スクリーンショット 2022-01-30 18.01.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/89553b1b-738c-9525-d174-ea87fe088e1b.png)


# 2.NibViewクラスの作成
- なぜNibViewクラスを作成するのかというと、後々、開発するときに１個NibViewクラスを作成しておけば、継承して使い回せて便利だからです。
- NibView.swiftファイルを作成

```swift:NibView.swift
import UIKit

class NibView: UIView {
    var view: UIView!
    override init(frame: CGRect) {
        super.init(frame: frame)
        xibSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        xibSetup()
    }
}

private extension NibView {

    func xibSetup() {
        backgroundColor = UIColor.clear
        view = loadNib()
        view.frame = bounds
        addSubview(view)

        view.translatesAutoresizingMaskIntoConstraints = false
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[childView]|",
                                                      options: [],
                                                      metrics: nil,
                                                      views: ["childView": view as Any]))
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[childView]|",
                                                      options: [],
                                                      metrics: nil,
                                                      views: ["childView": view as Any]))
    }
}

extension UIView {
    func loadNib() -> UIView? {
        let bundle = Bundle(for: type(of: self))
        guard let nibName = type(of: self).description().components(separatedBy: ".").last else {
            print("NibViewでERROR")
            return UIView()
        }
        let nib = UINib(nibName: nibName, bundle: bundle)
        return nib.instantiate(withOwner: self, options: nil).first as? UIView
    }
}
```

# 3.ViewにNibViewクラスを継承する
先ほど作ったNibViewクラスをContentViewクラスに継承します。

```swift:ContentView.swift
import Foundation

class ContentView: NibView {
    
}
```

# 4.xibのViewControllerにobjectsのViewをセット
セットしたViewのCustom ClassにContentViewと入力し、ContentViewを紐づける。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/efa960aa-0440-771b-d22e-7d6756b46481.png" width=80%>

# 5.Xibとswiftファイルの紐付け。
XibのViewControllerのFile'sOwnerでxibのViewControllerを紐づけます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/bc7fd46e-635f-fce4-0369-ffcbcb0da0ca.png" width=80%>
XibのViewのFiles'OwnerでxibのViewも紐づけます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/bff1d361-79ba-c13f-6caf-0f04693aa819.png" width=80%>
私はここで間違ってCustomClassに設定して沼にはまったので、必ずFiles'Ownerの方で設定するよう注意が必要です。


# 6.ContentViewController.xibでContentViewをIBOutletで接続します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/8855c88e-13ce-02b3-2534-6f9d0ecd938f.png" width=80%>

# 7.ContentView.xibのカスタムビューにUIlabelを配置してレイアウト
基本的にUIの配置などレイアウトはViewのXibでします。

Autolayoutで適当に制約（省略）。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/8ab2087c-e6ce-19da-7147-dbb97f8e4af7.png" width=80%>

一部分のみのカスタムビューを作る場合は、右のユーティリティエリアのSimulated MetricsのSizeをFreedom、TopBarとBottomBarをNoneに設定すると、実装しやすいです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/cc2dda4c-b614-ec58-a8f9-feba7d227e2c.png" width=40%>

# 8.Main.storyboardのViewControllerのCustom ClassをContentViewControllerに設定します。
表示させたいViewControllerにCustom classの紐付けをします。
今回は、デフォルトで設定されているViewは消しています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1161345/24801d4b-6cb8-9b69-a7e4-768876334d7d.png" width=80%>


# 注意
Files'Ownerの設定とCustomClassで設定がごちゃ混ぜになりがちなので注意が必要です。

# 参考
https://qiita.com/sadashi/items/fc9a9cff13af826482bc