iOSエンジニアのつぶやき

毎朝8:30に iOS 関連の技術について1つぶやいています。まれに釣りについてつぶやく可能性があります。

Xib で View を生成する時に知っておくといいこと

先日、うっかり ViewClass で指定した Xib で作成したカスタムビューのプロパティにアクセスし下記のように Error を出してしまいました。初心者の頃はよく分からずググったものコピペ なりで回避していましたが、そもそも何故これが Error になるのかを今回は紹介したいと思います。

    override func viewDidLoad() {
        super.viewDidLoad()
        hogeView.label.text = "hogehoge"
    }
    // Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

Xib で View を生成する方法

Xib で View を生成する方法は、大きく分けて View ClassFile's Owner を指定する2通りの方法があります。

View Class

f:id:yum_fishing:20200901213333p:plain

View Class は xib上の View に対してクラスを指定することで直接的に xib と参照を作ることができます。この方法は UINib を使用して View をコードから初期化する場合は、全てのオブジェクトが使用できる状態になっていることが担保されますが、Storyboardxib などで直接 View を生成する場合は基本的には nib-loadingではない(init(decode: NSCoder))ため、全ての View が初期化されていることは担保されません。(これが、View Class で作成したカスタムビューなどを Xib 上で生成した時に、プロパティへの参照が nil でクラッシュする原因と考えられます)

The order in which the nib-loading code calls the awakeFromNib methods of objects is not guaranteed. In OS X, Cocoa tries to call the awakeFromNib method of File’s Owner last but does not guarantee that behavior. If you need to configure the objects in your nib file further at load time, the most appropriate time to do so is after your nib-loading call returns. At that point, all of the objects are created, initialized, and ready for use.

developer.apple.com

つまり、基本的に View Class を指定した View を使用する場合には、コードでインスタンスを生成して使用する必要があります。例えば、UITableViewCell などは再利用性がありコードから生成するのが適切なので、 Xcode のテンプレートなどでも用意されていると考えられます。

File's Owner

f:id:yum_fishing:20200901213606p:plain

File's Owner は名前の通り Xib 上の View の保持先を指定することで、@IBOutlet などでクラスに View の参照を付けることができます。つまり、クラスと Xib で作成された View のインスタンスは別なので、nib-loading を適切なタイミングで呼ぶことで View の全てのオブジェクトが使用可能になっていることが担保されます。これによって、コードから生成される時は、init(frame: CGRect) で、StoryboardXib から生成される時は init?(coder aDecoder: NSCoder) から View を生成することができるようになります。

参考

developer.apple.com

qiita.com

qiita.com

その他の記事

yamato8010.hatenablog.com

yamato8010.hatenablog.com

yamato8010.hatenablog.com