だいたいそれでいいんじゃないの

つれつれなるkixixixixiの技術的なストック。http://reload.co.jp

[swift] UIViewのsubclassでのinitの挙動

UIViewのサブクラスを作ったときにinitでの挙動がどうなっているのかなーって疑問になったので自分のまとめ載せておきます。

init()自体をoverrideして初期化時の処理を追加したいときにかくべきなのはinit()なのかinit(fram:)なのか。
とりあえず、下記の挙動でうごきました。

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

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

コードのみで生成しているのですが、3つともないと落ちます。

調べてみると、override init()override init(frame: CGRect)がコードで生成した時に、 required init(coder aDecoder: NSCoder)がxibなどでつくったときに呼ばれるみたい。

それじゃコードで読んだときどの順番でよばれるのか?と思って調べてみました。

    var i = 0
    
    override init()
    {
        super.init()
        i++
        NSLog("init() cnt:%d", i)
    }
    
    override init(frame: CGRect)
    {
        super.init(frame: frame)
        i++
        NSLog("init(frame:) cnt:%d", i)
    }

    required init(coder aDecoder: NSCoder)
    {
        super.init(coder: aDecoder)
        i++
        NSLog("init(code):0 cnt:%d", i)
    }

こんなクラスを作って呼んでみると

  • subView.init(frame:rect)の場合
init(frame:) cnt:1
  • subView.init()の場合
init(frame:) cnt:1
init() cnt:2

おおおおお!init(frame:)は絶対先に呼ばれるのか!
というわけでひとまずはinit(frame:)に処理を書けばいいみたい。

xibをつかったときの挙動とかはまたあとで。

以上!