" async="async"> ', { cookie_domain: 'auto', cookie_flags: 'max-age=0;domain=.tistory.com', cookie_expires: 7 * 24 * 60 * 60 // 7 days, in seconds }); Mysteries of AutoLayout

Frontend/iOS

Mysteries of AutoLayout

데니 Denny 2021. 3. 1. 16:11
반응형
SMALL

이번 포스트에서는 WWDC 2015에 소개된 Mysteries of AutoLayout Part.2에 대한 내용을 간략하게 정리해보고자 합니다.

 

Mystery #7. Layout Cycle

The Layout Cycle

Application Run Loop : Application이 계속 반복적으로 실행됩니다.

Constraints Change : 제약조건에 변화가 생기면 변화된 제약조건이 적용될 때까지 Calculated Layout이 정의됩니다.

Deferred Layout Pass : 위에서 언급된 레이아웃이 최종 변경될 때까지 Deferred Layout Pass가 예약됩니다.

 

모든 Layout Pass가 되돌아 오게 되면, 뷰의 Hierarchy를 거쳐 뷰의 모든 프레임을 업데이트하게 됩니다.

 

Constraints Change

Constraints의 변화는 다음과 같은 상황에 발생합니다.

  • Constraints 표현식의 변화가 생겼을 때
  • Constraints의 Activation 혹은 Deactivation이 발생했을 때
  • Constant나 Priority가 변경되었을 때
  • View가 추가되거나 제거될 때

Layout Engine은 변경된 레이아웃을 다시 계산합니다.

Layout Engine에 있는 모든 변수는 새로운 값을 받게 되는데, 이 변수는 어떤 View의 origin이나 크기를 나타내는 값으로 설정됩니다.

View는 superview.setNeedsLayout() 함수를 호출합니다.

Deferred Layout Pass

  • 위치가 잘못된 뷰들의 위치를 재정렬합니다.
  • Constraints를 업데이트합니다.
  • View의 frame을 다시 지정합니다.
updateConstraints

updateConstraints를 하기 위해서는 setNeedsConstraints() 함수를 호출하면 일정 시간 후에 해당 뷰에 대한 제약조건을 갱신하는 함수가 실행되게 됩니다.

updateConstraints는 다음과 같은 경우에 구현할 수 있습니다.

- 제약 조건의 변경은 굉장히 느립니다. updateConstraints 내에서 제약 조건을 변경하는 것이 다른 시간에 제약 조건을 변경하는 것보다 실제로 빠릅니다. 왜냐하면 LayoutEngine Layout Pass에서 발생하는 모든 제약조건 변화를 일괄적으로 처리할있기 때문입니다.

이는 제약 조건을 개별적으로 활성화하는 것과는 반대로 전체 제약 조건의 활성화 제약 조건을 호출하여 얻는 것과 동일한 종류의 성능상 이점을 보여줍니다.

- View는 불필요한 변화들을 생성하게 되는데, View가 단지 setNeedsUpdateConstraints()를 호출하도록 하는 것이 효율적입니다. 그러고나서 update constraints pass가 전달되면, 제약조건이 configuration과 일치하도록 제약 조건을 한 번 재구성 할 수 있습니다.

 

Mystery #8. Interacting with Legacy Layout

frame vs. constraints

layoutSubviews를 상속하려는 경우에는 frame을 설정할 필요가 있습니다.

translatesAutoresizingMaskIntoConstraints

이 옵션은 frame이 constraints를 자동으로 생성해주는 옵션입니다.

Layout Engine에서 해당 View의 frame을 적용합니다.

만약 Constraints를 지정해주고 싶은 경우라면 이 옵션을 false로 설정해야 합니다.

Programmatically 생성된 View들은 기본적으로 위 옵션이 true로 설정되어 있기 때문에 잊지 말아야 합니다.

 

Mystery #9. Constraint Creation

Layout Constraint 생성하는 방식은 아래와 같은 방식으로 합니다.

[b.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:10];
[b.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:10];

Mystery #10. Constraint Negative Spacing

NSLayoutGuide / UILayoutGuide

UILayoutGuide는 다음과 같이 추가할 수 있습니다.

let guide = UILayoutGuide()
view.addLayoutGuide(guide)

여백에는 레이아웃 앵커를 사용할 수 없습니다.

UIView는 이제 layoutMarginsGuide를 노출하게되고 → 여백 내부의 뷰 영역을 나타냅니다.

var layoutMarginsGuide: UILayoutGuide

Mystery #11. Unsatisfable Constraints

Layout Log를 잘 이해하기 위한 방법

  • Accessibility Identifier을 설정한다.
  • Log에서 View를 식별할 수 있습니다.
  • Layout Guide에 Identifier를 설정합니다.
  • iOS에서는 constraintsAffectingLayoutForAxis를 사용할 수 있습니다.

Mystery #12. Resolving Ambiguity

Layout이 내가 원하는 대로 잘 보이지 않을 경우 다음과 같은 원인이 있을 수 있습니다.

  • 제약 조건이 너무 적을 경우
  • 제약 조건 우선순위에 있어 충돌이 발생했을 경우

진단도구를 이용해서 원인을 분석할 수 있습니다.

레이아웃 디버깅

Layout Engine에 필요한 정보가 무엇인지 생각합니다.
constarints가 올바르게 나오지 않는다고 판단될 때는 Log를 사용하세요.
Constraints 및 View에 대하여 Identifier를 추가하세요.
주기적으로 Ambiguity를 확인하십시오. (오랜 시간이 지나 복잡해질 경우 디버깅이 점점 더 어려워짐)

 

다음과 같은 도구를 사용하여 문제를 해결합니다.

  • 인터페이스 빌더의 아이콘
  • 디버거보기
  • lldb의 메소드

 

간략하게 정리해보았습니다. 유익한 내용이었기를 바랍니다.

반응형
LIST