viewDidLayoutSubviewsメソッド、layoutSubviewsメソッド内でコードでレイアウトを組むことで、画面の向きの変更、ナビゲーションの表示など様々な理由で表示に変化があった時にレイアウトが更新されます。
viewDidLayoutSubviews
ViewControllerのviewDidLayoutSubviewsメソッドはViewControllerの表示、画面の向きの変更など、様々な理由でViewControllerのviewのframeが更新された時に呼び出されます。
以下はラベルとボタンを表示させているだけのコードです。
import UIKit
class ViewController: UIViewController {
var label: UILabel!
var bt: UIButton!
//ラベル描画
func createLabel(){
let padding:CGFloat = 20
label.text = "ラベル"
label.textAlignment = .center
label.backgroundColor = .red
label.frame = CGRect(x: view.frame.origin.x+padding, y: 50, width: view.frame.width-(padding*2), height: 50)
}
//ボタン描画
func createBt(){
let btWidth:CGFloat = 100
bt.setTitle("ボタン", for: .normal)
bt.titleLabel?.textAlignment = .center
bt.backgroundColor = .blue
bt.frame = CGRect(x: label.frame.maxX-(label.frame.width/2+btWidth/2), y: label.frame.maxY+20, width: btWidth, height: 30)
}
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel()
bt = UIButton()
view.addSubview(label)
view.addSubview(bt)
}
//ラベル、ボタンの描画(レイアウト)をviewDidLayoutSubviewsメソッド内で実行
override func viewDidLayoutSubviews() {
createLabel()
createBt()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
● デバイス表示

layoutSubviews
カスタムViewクラスを作成した場合はlayoutSubviewsメソッドを使います。
layoutSubviewsメソッドは親Viewのframeが変更された時など、レイアウトを変更するべき時に呼び出されます。
CustomViewクラス
import UIKit
////nitializer 'init()'とObjective-Cセレクタ 'init'は暗黙の初期化子 'init()'と同じObjective-Cで衝突します
//extension UIView{
// convenience init() {
// self.init(frame: .zero)
// }
//}
class CustomView: UIView {
var label:UILabel!
init(){
label = UILabel()
super.init(frame: .zero)
self.addSubview(label)
}
// override init(frame: CGRect){
// super.init(frame: frame)
// label = UILabel()
// self.addSubview(label)
// }
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//ラベルの描画メソッド(ラベルは赤色)
func createLabel(){
label.frame = CGRect(x: bounds.origin.x+50, y: bounds.origin.y+50, width: bounds.size.width-50*2, height: 100)
label.backgroundColor = .red
}
override func layoutSubviews(){
super.layoutSubviews()
//ラベルの描画実行
createLabel()
}
}
32行目
ラベルの描画でframeではなく、boundsを使用しています。
frameは画面(親)を基準とする座標ですが、boundsは自身(CustomView)を基準とする座標です。
「bounds.origin.x+50」はCustomViewの(0,0)からx軸に+50の位置にラベルがあるということになります。
「bounds.size.width-50*2」はCustomViewの横幅から100引いた大きさになります。CustomViewの描画についてはViewControllerクラス内で設定しています。
ViewControllerクラス
import UIKit
class ViewController: UIViewController {
var customView: CustomView!
override func viewDidLoad() {
super.viewDidLoad()
//CustomViewを生成し、viewに追加
customView = CustomView()
view.addSubview(customView)
}
//CustomViewを描画するメソッド(CustomView自体は青色)
func createParentLabel(){
customView.frame = CGRect(x: view.frame.origin.x + 50,
y: view.safeAreaInsets.top + 50,
width: view.frame.width - 50 * 2,
height: 200)
customView.backgroundColor = .blue
}
//CustomViewの描画(レイアウト)をviewDidLayoutSubviewsメソッド内で実行
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
//CustomViewをviewに描画
createParentLabel()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
● デバイス表示
