viewDidLoad 내에서 view의 width 등이 0이되어 버려 얻을 수 없다 (Swift의 화면 레이아웃 주위의 비망록)

Swift 레이아웃으로 막힌 포인트



swift의 레이아웃 주위에 막혔으므로, 비망록도 벌써 정리해 두려고 생각합니다. swift5, Xcode12입니다. storyboard나 swiftUI가 아니라 swift(코드)로 쓰고 있습니다. (storyboard나 swiftUI 사용하면 굉장히 편합니다만… 레이아웃을 고집하면 코드로 쓰는 것이 가장 좋은 것 같습니다.)

viewDidLoad 내에서 view의 width 등이 0이되어 버려 얻을 수 없다



위와 같습니다만, 아래의 코드와 같이 viewDidLoad내에서 view1의 width와 height의 값이 0이 되어 버려, view2가 draw 할 수 없습니다.

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 라이프사이클
    보기 수명 주기 2
    자동 레이아웃(Anchor)
    자동 레이아웃 (NSLayoutConstraint)
    레이아웃 및 제약 업데이트
    레이아웃, 제약, 드로잉 타이밍 등

    좋은 웹페이지 즐겨찾기