Swift TIL(71)- updateConstraints 와 layoutSubview 의 사용시 주의점

웰디(Well-D)·2023년 11월 6일
0

Sweet & Soft, SWIFT

목록 보기
71/76

앱의 내부 매커니즘을 앱의 생명주기, 뷰 컨트롤러의 생명주기, 드로잉 싸이클을 기준으로 배워보았다.
중요한 것은 시점을 알고 해당 시점의 적절한 메서드를 재정의해서 구현하는 것!

이번 부분에서 내가 트라이하고 고민해 본 부분은 다음과 같다.

해당 고민을 같이 보기 위해 알아둬야할 부분을 간단히 정리하면,

사전에 알아야 하는 지식

드로잉 싸이클 내에서는 updateConstraints => LayoutSubview => View 를 통해서 오토레이아웃 제약조건을 설정하고, 이를 배치하고, 실제로 애니메이션등을 그리게 된다.

  1. 실제로 제약조건은 updateConstraints 에 존재해야한다
    기본적으로 frame 을 쓰는 코드는 전부 updateConstraints 메서드 내부에 존재해야 된다고 해서 테스트를 해보았다.

만약 layoutSubview 가 아닌 updateConstraints 에 구현하면 어떻게 될까?

왜 됨..? 이왜진 이였지만 테스트 해본 결과 다음과 같았다.
⇒ 실제 anchor 등의 오토레이아웃 제약조건은 안 됨, cornerRadius 등 실제 제약 조건이 아닌 셋팅에 가까운 코드는 됨

1-1. cornerRadius 등은 frame 을 사용해도 구현이 잘 된다

override func updateConstraints() {

            self.layer.cornerRadius = self.frame.width / 2
            // self.frame => 원점과 크기로 지정되어있는 직사각형
            super.updateConstraints()
        }

1-2. 다음과 같이 self.frame 에 다시 속성을 할당해줘야하는 오토레이아웃 제약조건등은 구현이 안 된다.(에러는 안남)

 //참고로 다음과 같은 제약사항은 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)

  1. updateConstraints 메서드 내부에서 super.updateConstraints(재정의 하므로 필요) 는 가장 마지막에 써야 한다.

만약 updateConstraints 메서드 내부에서 super. updateConstraints을 먼저 쓰면 어떻게 될까?

=> 당연히 안된다. (제약조건에 한해서)

에러를 내기 위해 작성해 본 코드 2가지

2-1. 제약조건을 super 보다 먼저 썼을때

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뒤에 제약코드를 작성하니까) 에러가 발생했다고 볼 수 있다

(참고)

2-2. print 를 super 뒤에 썼을때

=> 에러가 나지 않는다.
이 코드는 잘 동작함(이런코드를 쓸일은 없겠지만)

override func updateConstraints() {
        super.updateConstraints()
        print("지금호출하면 안되나요") // 이건 된다
        
    }

⇒ 터미널에 메세지 정상적으로 출력됨

결론

autolayout 오토레이아웃과 관련된 코드가 super 보다 아래에 작성되었을때 문제가 된다 (당연하다)

profile
Wellness 잘사는 것에 진심인 웰디입니다. 여러분의 몸과 마음, 통장의 건강을 수호하고싶어요. 느리더라도, 꾸준히

0개의 댓글