こんにちは。
調べてもどうしても出てこなくて困っています。
xibのView作成についてなど2つ質問させていただきたいです。
(実行環境 Xcode 8.2.1 / Swift 3.0.2)


1つ目

class CustomView: UIView {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        let view = Bundle.main.loadNibNamed("Custom", owner: self, options: nil)?.first as! UIView
        view.frame = bounds
        addSubview(view)
    }
}

このようにxibファイルのViewをロードして、viewの子としてaddし、サイズを調節することで
CustomViewとしていることを記事などで調べていました。また、ここで

translatesAutoresizingMaskIntoConstraints = false

と、システムが管理するAutoResizeMaskの自動制約追加を無効にして
AutoLayoutを設定している記事もありました。
どちらにしても、実行時にはサイズが調節され、同じサイズになっています。

view.frame = bounds

とする方では、initの時点ではViewのサイズなどのレイアウトは決まっていないはずなのです。
私はiPhone5のサイズ(320 × 568)のViewControllerをStoryboardで用意し、

directory
CustomViewにはViewControllerの持つViewに対して上下左右 0 と制約をつけて
iPhone6+(414 × 736)で実行しました。
もちろん、実行結果はCustomViewが画面いっぱいに表示されるのですが、

view.frame = bounds

このようにレイアウトが確定される前にこの処理をしても
(管理されるViewControllerのサイズなどが確定するviewDidLayoutSubViewsよりも前に
このinitは呼ばれる)
サイズがピッタリに合うのが何故か分かりません。

print(view.frame.size)

などとサイズを確認しても、ここでは320 × 568と表示されます。
(実際の実行時のサイズは414 × 736です。)

2つ目

ある記事でIB上でAutoLayoutを設定したViewには、自動的に

translatesAutoresizingMaskIntoConstraints = false

が設定されて、

view.frame = CGRect(x: 100, y: 100, width: 100, height: 100)

のように、直接変更はできないようになるとあり、確かに自分自身もそのような経験があったような気がしています。しかし、現在ではtranslatesAutoresizingMaskIntoConstraintsに関係なく直接frameなどで位置やサイズの調節ができるのですが、iOS10やXcode8.0などで変更されたのでしょうか?




少しUIViewのリファレンスを見直して見ました。気になった関数やプロパティは以下で

  • autoresizesSubviews 自動リサイズを利用するか(教えて頂いたもの)
  • requiresConstraintBasedLayout 正確に制約が機能する必要があるか(get only)
  • layoutSubViews 制約や自動リサイズよりもサブViewのレイアウトを正確に行う必要がある場合に設定

もし、frameなどの直接指定を行いたい場合は、カスタムクラス内でlayoutSubViews()を
overrideするのが良いのかなというのが現状の理解です...iOSレイアウトについてのまとめ

class CustomView: UIView {

    var subView: UIView!

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        subView = Bundle.main.loadNibNamed("Custom", owner: self, options: nil)?.first as! UIView
        //自動リサイズを無効にして、
        autoresizesSubviews = false
        //以下を実行するとViewのサイズはIBの 320 × 568 (6+実行時でも320 × 568 とぴったり合わない)
        //subView.frame = bounds
        addSubview(subView)
    }

    //自動リサイズを無効にしても、IB上でAutoLayoutをCustomViewに設定しているのでレイアウト確定時に呼ばれてサイズがぴったり合う
    //(ViewControllerの持つViewに対してautoresizesSubviews = false を設定してもぴったり合ったので、
    //これはAutoLayoutによってレイアウトが確定されることが分かりました。)
    override func layoutSubviews() {
        subView.frame = bounds
    }
}