Xcode
iOS
Swift

カスタムUIViewの作り方

背景

iOSアプリを開発していると、作成したViewを別の場所で使い回したい場合があります。またiOSアプリ向けのSDKを開発する場合、SDK側でViewを定義しておいて、クライアントアプリ側で使ってもらうという状況も想定されます。そのような場合は独自のUIViewクラスを作成し、他の場所でも再利用できるようにしておくとよいでしょう。

カスタムUIViewクラスを作成

File -> New -> FileからCocoa Touch Classを選択し、UIViewクラスを継承したCustomViewクラスを作成します。

Screen Shot 2018-02-03 at 15.08.30.png

CustomViewクラス
import UIKit

class CustomView: UIView {

}

CustomView.xibの作成

UIの実装をコードで行う方法もありますが、本記事ではxibを利用してUIを組み立てていくことにします。File -> New -> FileからViewを選択し、先ほど作成したクラスと同名のCustomView.xibを作成します。

Screen Shot 2018-02-03 at 15.13.20.png

サイズの調整

本記事では幅320*高さ50のバナーサイズのViewを作成することにします。まずは右側のAttributes inspectorからSizeを選択し、"Freeform"を指定してください。

Screen Shot 2018-02-03 at 15.20.55.png

次に、Size inspectorで幅と高さ(320 * 50)を指定します。

Screen Shot 2018-02-03 at 15.24.14.png

これでバナーサイズのシンプルなViewが作成されました。

Screen Shot 2018-02-03 at 15.25.51.png

要素の配置

次にバナーの上にいくつかの要素を追加してみましょう。右下のObject libraryからImage Viewを選択し、ドラッグ&ドロップでViewの上に追加してください。
Screen Shot 2018-02-03 at 15.32.50.png

ImageViewはバナーの左端に正方形のアイコンのような形で置くことにします。ImageViewを選択した状態で、右側のSize inspectorを下図(x: 0, y: 0, width: 50, height: 50)のように修正してください。

Screen Shot 2018-02-03 at 15.39.07.png

同じ要領で、ImageViewの右側にUILabelを追加してみます。位置とサイズは(x: 50, y: 0, widht: 270, height: 50)となります。

Screen Shot 2018-02-03 at 15.43.40.png

コードとの接続

最後にxibとコードの接続を行います。左側のPlaceholdersからViewを選択状態にし、

Screen Shot 2018-02-03 at 15.50.04.png

続いて右側のIdentity inspectorでクラス名をCustomViewに指定することで、xibとクラスの連結を行います。

Screen Shot 2018-02-03 at 15.49.43.png

次に要素の接続を行います。Xcode右上のリングが二つ重なったようなマーク(Show the Assistant editor)を選択してください。

Screen Shot 2018-02-03 at 15.54.29.png

するとCustomViewクラスのコードが右側に表示されるので、

Screen Shot 2018-02-03 at 15.58.28.png

Ctrlを押しながらドラッグ&ドロップでImageViewをコード部分に引っ張って接続してください。

Screen Shot 2018-02-03 at 15.59.13.png

同様にLabelの接続も行い、各要素のproperty登録が完了しました。

Screen Shot 2018-02-03 at 15.59.59.png

CustomViewを再利用可能な状態にする

最後に下記のようにinitメソッドを実装することで、CustomViewを他の場所でも再利用可能な状態にします。

initを実装したCustomViewクラス
class CustomView: UIView {
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var label: UILabel!

    override init(frame: CGRect) {
        super.init(frame: frame)
        loadNib()
    }

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

    func loadNib() {
        if let view = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? UIView {
            view.frame = self.bounds
            self.addSubview(view)
        }
    }
}

注意点

本記事ではView要素のConstraintの設定を省略しています。実際の開発では各要素のConstraintを設定してマルチサイズに対応するとよいでしょう。