LoginSignup
0
0

More than 1 year has passed since last update.

viewDidLoad内で、viewのwidthなどが0になってしまい取得できない(Swiftの画面レイアウト周りの備忘録)

Last updated at Posted at 2021-07-25

Swiftのレイアウトで詰まったポイント

swiftのレイアウト周りで詰まったので、備忘録もかねてまとめておこうと思います。swift5、Xcode12です。storyboardやswiftUIではなく、swift(コード)で書いています。(storyboardやswiftUI使えば凄い楽なんですけどね…レイアウトにこだわるとコードで書くのが一番良いらしいです。)

viewDidLoad内で、viewのwidthなどが0になってしまい取得できない

上記の通りですが、下記のコードのようにviewDidLoad内でview1のwidthとheightの値が0になってしまい、view2が描画できていません。


view.backgroundColor = UIColor.lightGray
let view1 = UIView()
let view2 = UIView()
self.view.addSubview(view1)
self.view.addSubview(view2)

view1.translatesAutoresizingMaskIntoConstraints = false
view1.backgroundColor = UIColor.green
view1.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.5).isActive = true
view1.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.5).isActive = true
view1.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
view1.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true

view2.translatesAutoresizingMaskIntoConstraints = false
view2.backgroundColor = UIColor.blue
view2.frame.size.width = view1.frame.size.width / 2
view2.frame.size.height = view1.frame.size.height / 2
//view1のwidthとheightは0になってしまう
view2.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
view2.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true

上記コードの実行結果:

期待される結果:

viewDidLoad内でview1に対して、view1.widthAnchor.constraint()を用いてオートレイアウトを使った。そして、そのviewのwidthの値を用いて、下記の方法でview2の長さを決めようとした。

原因 

原因は、制約やレイアウトが反映されていないため。viewDicLoad内でviewに制約を加えても、その場では更新されない。

解決策

1. レイアウトでのサイズ指定(widthやheight)をせずに、制約としてサイズの指定をする。

AnchorやNSLayoutConstraintで制約を指定する。

//widthやheightでレイアウトの指定をしない
view2.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: 0.4).isActive = true
view2.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.4).isActive = true

2. 制約やレイアウトを更新する。

レイアウトが更新されないなら、そのタイミングで更新するだけ。
下記コードではうまく更新できない。タイミングの問題かと思い、色々なタイミングで実行したけどできない。なんでだろ?

self.view.updateConstraintsIfNeeded()
self.view.layoutIfNeeded()

まとめ

奥が深いなぁ…
下記引用です。

  • Viewの読み込み
  • 制約の追加(AutoLayout)
  • 制約を元にViewのframeを計算(レイアウト)
  • frameの位置に描画(レンダリング)

という順番で読み込むので、オートレイアウトがされ、frameの値が決められた後にframeを直接編集するとオートレイアウトで決定した制約が死んでしまうのかな…なるほど?

今後の課題

基本的にはオートレイアウトですべて決定するのが良さそう…?
もしくは、他のオートレイアウトの方法との組み合わせはいける?
widthAnchorやheightAnchorのAnchorについても今度調べようかなと思いました。

参考文献

viewのライフサイクル
viewのライフサイクル2
オートレイアウト(Anchor)
オートレイアウト(NSLayoutConstraint)
レイアウトと制約の更新
レイアウト・制約・描画のタイミングなど

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0