xibで作成したViewのサイズを合わせる処理について
こんにちは。
調べてもどうしても出てこなくて困っています。
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で用意し、
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
}
}