앱의 내부 매커니즘을 앱의 생명주기, 뷰 컨트롤러의 생명주기, 드로잉 싸이클을 기준으로 배워보았다.
중요한 것은 시점을 알고 해당 시점의 적절한 메서드를 재정의해서 구현하는 것!
이번 부분에서 내가 트라이하고 고민해 본 부분은 다음과 같다.
해당 고민을 같이 보기 위해 알아둬야할 부분을 간단히 정리하면,
드로잉 싸이클 내에서는 updateConstraints => LayoutSubview => View 를 통해서 오토레이아웃 제약조건을 설정하고, 이를 배치하고, 실제로 애니메이션등을 그리게 된다.
- 실제로 제약조건은 updateConstraints 에 존재해야한다
기본적으로 frame 을 쓰는 코드는 전부 updateConstraints 메서드 내부에 존재해야 된다고 해서 테스트를 해보았다.
왜 됨..? 이왜진 이였지만 테스트 해본 결과 다음과 같았다.
⇒ 실제 anchor 등의 오토레이아웃 제약조건은 안 됨, cornerRadius 등 실제 제약 조건이 아닌 셋팅에 가까운 코드는 됨
override func updateConstraints() {
self.layer.cornerRadius = self.frame.width / 2
// self.frame => 원점과 크기로 지정되어있는 직사각형
super.updateConstraints()
}
//참고로 다음과 같은 제약사항은 layoutSubview 아닌 updateConstraints 에서는 에러는 안나지만 구현이 안된다
myButton.frame.size = CGSize(width: self.frame.size.width/2, height: self.frame.size.height/2)
myButton.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
- updateConstraints 메서드 내부에서 super.updateConstraints(재정의 하므로 필요) 는 가장 마지막에 써야 한다.
=> 당연히 안된다. (제약조건에 한해서)
에러를 내기 위해 작성해 본 코드 2가지
override func updateConstraints() {
super.updateConstraints()
self.translatesAutoresizingMaskIntoConstraints = false
// 참고로 해당 속성은 반드시 false 여야한다
// 정의 참고 : If you want to use Auto Layout to dynamically calculate the size and position
// of your view, you must set this property to false
self.heightAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1).isActive = true
}
Exception NSException * "The layout constraints still need update after sending -updateConstraints to <ViewCycleCustomView.MyButton: 0x151506810; baseClass = UIButton; frame = (0 0; 0 0); opaque = NO; backgroundColor = UIExtendedSRGBColorSpace 1 1 0 1; layer = <CALayer: 0x60000204b860>>.\n
ViewCycleCustomView.MyButton or one of its superclasses may have overridden -updateConstraints without calling super. Or, something may have dirtied layout constraints in the middle of updating them. Both are programming errors." 0x0000600002e66fd0
정확하게 updateConstraints 를 재정의하면서 super 을 부르지 않았을 수 있다고 상속에 대한 내용을 지적하고 있다!
해석
레이아웃 제약들은 updateConstraints 가 보내진 후에도 업데이트가 필요하다고 되어있다.
즉 오토레이아웃을 설정이 끝난 후에 update 해줘야하는데 이미 updateConstraints를 보내놓고 또 제약을 설정하려고 하니(super.upadateConstraints뒤에 제약코드를 작성하니까) 에러가 발생했다고 볼 수 있다
(참고)
=> 에러가 나지 않는다.
이 코드는 잘 동작함(이런코드를 쓸일은 없겠지만)
override func updateConstraints() {
super.updateConstraints()
print("지금호출하면 안되나요") // 이건 된다
}
⇒ 터미널에 메세지 정상적으로 출력됨
autolayout 오토레이아웃과 관련된 코드가 super 보다 아래에 작성되었을때 문제가 된다 (당연하다)