티스토리 뷰

[iOS 오토레이아웃 가이드] Advanced Auto Layout - Changing Constraints


제약조건을 변경하는 것은 constraint equqation을 바꾸는 작업입니다.

다음과 같은 동작이 제약조건을 바꿉니다.

- 제약조건은 활성화 하거나 비활성화
- 제약조건의 constant value 변경
- 제약조건의 우선순위 변경
- 뷰를 뷰 계층구조에서 삭제하는 것 ( 뷰를 제거하면 뷰와 관련된 모든 제약조건이 제거되므로)
- 컨트롤러나 뷰의 속성을 변경하는 것
- 뷰 구조를 변경하는 것

이렇게 제약조건에 변화가 일어나면 시스템은 'deferred layout pass'예약합니다.

일반적으로 이러한 변화를 언제든 만들 수 있습니다. 이상적으로 대부분의 제약조건은 IB상에서 설정을 끝내거나 코드를 할경우에는 뷰컨트롤러의 viewDidLoad와 같은 초기설정에서 만들어져야 합니다. 만약 런타임시에 동적으로 제약조건을 변경하려면 어플리케이션 상태가 변활 때 바꾸는 것이 좋습니다. 예를 들면 버튼이 눌려질 때 바꾸고 싶다면 버튼액션 메서드에서 바로 제약조건을 변경합니다.

가끔 성능을 위해 모든 변화를 한 번에 처리하는 게 필요할 수도 있습니다. 이와 관련해서는 아래 'Batching Changes'를 보시면 됩니다.

The Deferred layout Pass

영향받는 뷰의 프레임을 바로 업데이트하기 전에, 오토레이아웃은 layout pass를 가까운 미래에 예약합니다. 이 defeered pass는 layout의 제약조건을 업데이트하고 뷰계층에 있는 모든 뷰의 frame들은 계산합니다.

'setNeedsLayoout'메소드나 'setNeedsUpdateConstraints'메소드를 이용하면 'deferred layout pass'를 조절할 수 있습니다

'deferred layout pass'는 뷰계층을 통과하는 2개의 passes와 관련이 있습니다.
update pass와 layout pass입니다/

1. 'update pass'는 제약조건을 업데이트
2. 'layout pass'는 뷰의 frame을 재위치 시킵니다.

Update Pass

시스템은 뷰 계층을 돌면서 모든 뷰컨트롤러의 updateConstraints 메소드를 호출하고 모든 뷰의 updateConstraints메소드를 호출합니다. 제약조건의 변화를 최적화하려면 이 메서드들은 오버라이드 하면 됩니다. (see Batching Changes)

Layout Pass

시스템은 뷰 계층을 다시 돌면서 뷰컨트롤러의 viewWillLayoutSubviews를 호출하고 모든 뷰의 layoutsubviews(layout in OS X)를 호출한다. 기본적으로 layoutsubviews 메소드는 각 subview의 프레임을 업데이트하는데 오토레이아웃 엔진에 의해 계산된 사각형을 기반으로 한다. 이 메소드를 오버라이드 해서 layout을 수정할 수 있다. (see Custom Layouts)

Batching Changes

제약조건이 수정되되고 바로 업데이트가 일어나는게 깔끔하고 쉽다. 제약조건 변화를 즉시 업데이트 하지 않고 지연시키면 코드가 복잡하고 이해하기 어려워집니다. 

그러나 성능을 위해서 모든 제약조건 변화들을 한 번에 처리해야 할 때가 있습니다. 이 작업은 제약조건 변화를 업데이트하는 게 너무 느리거나 여러번 중복 변경을 하는 경우에만 써야합니다. 

일괄처리하려면 제약조건을 가지오 있는 뷰의 'setNeedUpdateConstraints'메소드를 호출하면 됩니다. 그리고 변화가 생긴 제약조건을 수정하기 위해서 updateConstraints메소드를 오버라이드하세요 

중요!
updateConstraints를 구현할 때는 가능한한 효율적이여야만 합니다. 모든 제약조건을 비활성화 하지 말고 필요한 제약조건만 활성화시키세요. 대신 앱은 제약조건을 추적하는 몇몇 방법이 있어야 하며, update pass가 일어나는 동안 유효성을 검사할 수 있어야만 합니다. 변경해야 하는 제약조건만 변경해야 합니다. 각 update pass가 진행하는 동안 현재 앱의 상테에 대한 적절한 제약조건이 있는지 확실히 해야 합니다. 

updateConstraints를 커스텀할 때는 항상 마지막에 super.updateConstriants()호출해야 합니다.

updateConstraints메소드 안에서 setNeedUpdateConstraints를 호출하지 마세요. 부르면 또 다른 update pass가 일어나서 feedback loop를 발생시킵니다.

Custom Layouts

오토레이아웃 엔진이 반환한 결과값을 변경하기 위해 viewWillLayoutSubviews나 layoutSubviews를 오버라이드하세요. 

중요!
가능하다면 모든 레이아웃을 만들기 위해서 제약조건을 사용하세요. 그래야 보다 견고하고 디버그하기 쉽습니다. 제약조건으로만 레이아웃을 만들 수 없을때 만 위 함수를 오버라이드해서 사용하세요.

위 함수를 오버라이들 할 때, 레이아웃이 일치하지 않은 상태일 수 있습니다. 일부 뷰는 이미 배치가 됐지만 다른 뷰는 그렇지 안을 수 있습니다. 뷰 계층을 수정할 때는  feedback loop를 만들 수 도 있으니 조심해야 합니다. 다음은 feedback loop를 피하는 데 도움이 되는 규칙입니다.

- 위 메소드를 오버라이드할 때 항상 상위뷰의 구현도 호출해야 합니다.(super.layoutSubviews())

- 하위 트레이 있는 뷰의 레이아웃을 안전하게 무효화 할 수 있습니다. 단, 이 작업을 할 때는 상위뷰의 구현을 호출하기 전에 해야 합니다.

- 하위 뷰? 하위 뷰 계층? 밖에 있는 뷰의 레이아웃은 무효화하지 마세요. (자식뷰의 관해서만 작업?) feedback loop를 만들수도 있습니다.

- 방금 업데이트를 완료했기 때문에 setNeedsUpdateConstraints를 호출하면 feedback loop가 발생합니다.

- setNeedLayout 함수도 호출하면 feedback loop가 발생합니다.

- 제약조건을 변경하는 것은 매우 조심해야 합니다. 잘못하면 포함하지 않은 뷰를 무효화시킬 수 있습니다.


https://www.youtube.com/watch?v=xjArhdrqAn8&t=1254s


https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/ModifyingConstraints.html#//apple_ref/doc/uid/TP40010853-CH29-SW1

반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함