[iOS] Mysteries of Auto Layout, Part 1

mmim·2022년 8월 15일
0

Mysteries of Auto Layout, Part 1

WWDC Mysteries of Auto Layout, Part 1

😎 AutoLayout이란?

Auto Layout is a powerful constraint-based layout engine that can drive complex and dynamic interfaces on both iOS and OS X.

‼️ 한마디로 AutoLayout은 constraint-based 레이아웃 엔진이다.

🪄 Mystery 1: maintainable layouts

StackView

🔑 StackView를 사용하면
1) StackView는 자식 레이아웃을 알아서 관리하기 때문에 제약을 간소화할 수 있다.
2) StackView로 axis에 따른 alignment와 distribution을 설정할 수 있다.

alignment

horizontalvertical

distribution

demo

demo 예시를 통해 StackView의 장점을 말하고자 하는 파트

  • ⭐️ build와 maintain이 편리하다!
    • 1️⃣ 첫번째 목표: 아래처럼 복잡한 제약을 가지는 UI를 StackView를 통해서 간단히 표현해보자!
  • 최상위 StackView와 상위 뷰와의 오토 레이아웃만을 설정해주었다.
    ➡️ 첫번째 문제 상황: 아래처럼 Segmented Control이 늘어났다.
  • 이유: 모든 priority가 동일하다.
    ➡️ 해결: segmented control의 content-hugging priority 와 content compresstion priority를 올린다.

  • 두번째 문제 상황: 레이블과 별점 사이에 새로운 버튼을 추가하라는 요청이 있다.
    ➡️ 해결: StackView에 버튼 drop!(addArrangedSubview)

  • ⭐️ animation 적용 쉽다!

    • 레이아웃이 망가지지 않고 애니메이션이 적용된다.
  • ⭐️ StackView의 장점 요약

    • 만들기 쉽다.
    • 유지하기 쉽다.
    • 많은 구성요소를 넣을 수 있다.
    • 가볍다.(모든 부분 background render할 필요 없고 특별한 transform Layer class가 render 할 필요 없게 해준다. 그래서 이게 스택뷰를 빠르게 동작하도록 해준다)

🪄 Mystery 2: changing constraints

📢 다양한 iPhone의 화면 크기가 있다. 이러한 모든 환경에서 작동하도록 layout을 만들고, 단일 화면에 대해 반복하는 시간을 줄여햐한다.
그래서 대부분의 사람들은 아래 그림처럼 몇가지 view와 몇가지 제약을 만들어 일종의 블랙홀에 던진다.
블랙홀안에선 무언가 일어난다. 그리고 우리의 layout이 튀어나온다.

📢 지금부터 "블랙홀(???박스)" 미스테리의 일부를 해결하고 매번 원하는 layout에 도달하도록 하고자 한다.
그 시작은 changing constraints!

  • 이전에는 view의 constraints를 추가/삭제(add/remove)하는 개념이 있었다.

  • ‼️ 더이상 이 개념을 사용하지 말아라!

  • 뷰에 제약조건을 추가/삭제(add/remove)하는 것 보다는 activate, deactivate를 하는 것이 더 좋다!

  • activate, deactivate의 장점

    • contraints가 container를 알아서 찾아간다.
    • constraints를 효과적으로 추가할 수 있다.
    • 레이아웃 조절을 위해 모든 뷰를 알 필요가 없다.
  • Things to keep in mind

    • self.view.constraints의 모든 것을 비활성화하지 말아라.
    • ‼️ 그냥 하지 말아라.(이유는 다음에 설명😎)

contraints를 add, remove 했을 때, 문제 예시

여기 행성을 보여주는 iPad app이 있다. 이것은 멀티스크린이 가능하다.

옆에 다른 app을 켜고 왼쪽 스크린 크기를 키웠다가 줄였더니, 행성의 배열이 바뀌었다.

이를 해결하기 위해 constraints를 remove로 하도록 했다.

그랬더니 두개의 앱중 하나가 이상하게 나오고 그것을 다시 보이게 했더니 이상하게 나온다.
(여기서 sharedConstraints 라는 개념이 나오는데 뭔지 모르겠음 😅)

이처럼 이상하게 나오는 것을 확인할 수 있다.
그러므로 remove로 하게된다면 constarints가 이상하게 바뀐다.

따라서 특성 컬렉션이 변경되면 변경해야 할 수 있는 다른 제약 조건 집합이 활성화되어 있는지 각 환경에서 확인하고 확인한다.
여기에 행성과의 수직 정렬을 구별하는 8개의 제약 조건이 있는 두 개의 배열이 있다.
따라서 활성화되어 있는지 확인하고 제거하거나 더 이상 원하지 않는 것을 비활성화하고 새 것을 활성화하면 된다.

💡 솔직히 오래전 코드라 이해하기 어렵다. 그냥 하지마라‼️
모든 레이아웃을 deactivate(deactivate self.view.constraints)하지 마라!
➡️ 레이아웃이 이상하게 잡힌다.

🪄 Mystery 3: view sizing

intrinsic content size

  • contents에 맞게 사이즈를 결정한다.

  • 정확한 레이아웃 사이즈를 보장하지는 못한다.
    ➡️ 이유: adaptability 떄문이다. 이것이 strectch, shirnk 뷰를 하기 때문에 보장할 수 없다.

  • intinsicContentSize를 override해서 사용할 수 있는 3가지 요인들이 있다.

    1. 사이즈 정보가 constraints에서부터 오지 않을 경우에 사용한다.
    2. 만약 뷰가 커스텀으로 drawing될 때 사용한다.
    3. invalidate를 책임져야할 떄 사용해야한다. 왜냐하면 이것이 dynamic size, localization에 따라 사이즈가 동적으로 변하기 떄문이다.

🪄 Mystery 4: Self-Sizing Table View Cells

1️⃣ 문제:

🔨 해결:
레이블 레이아웃 조절: top space to container margin & bottm space to container margin

2️⃣ 문제:

➡️ 여전히 문제 존재: 레이블이 충분히 크지 않아서 이미지가 잘림

🔨 해결:
레이블이 최소한 이미지 높이는 되어야 한다는 조건이 필요하다!
이미지와 레이블 높이를 맞춘다.

관계식이 ">="이 되도록 변경

최종 해결:

🪄 Mystery 5: Priority

ambiguity는 언제 발생?

  • 레이아웃 조건이 부족할 때
  • equal-nonrequired priority
    ➡️ layout engine이 임의로 레이아웃을 선택
  • 레이아웃 수치가 같으면 모호함!
➡️ view content 우선도를 required 하지마라!! (ex. localization에 대응 못함)
  • 기본적으로 세팅하는 것을 요구하지 않는다. 그러나 이는 만족스럽지 못한 constraints를 보여줄 수 있다.

  • 1️⃣ 문제: 기본 content hugging 우선도가 250으로 동일 -> 레이아웃 엔진은 뭘 선택할지 몰라서 발생하는 문제

  • 🔨 해결: 버튼의 content hugging을 낮춘다.
  • 2️⃣ 문제: 기본 compression resistance가 750으로 동일
  • 🔨 해결: 모든 text가 보인다!

🪄 Mystery 6: Alignmnet

Aligning Baselines

  • first baseline: 첫 줄의 글자 아래 부분
➡️ 텍스트 줄이 늘어도 버튼의 위치는 동일
  • last baseline: 마지막 줄의 글자 아래 부분

leading & trailing > right & left

localization(글 작성 방향에 따라)

아랍어 같은 부분에서 오른쪽에서 왼쪾으로 읽으므로 지역화에 대응되어있지 않다.

leading, trailing으로 해주면 다른 나라에 맞게 설정해줄 수 있다.

Alignment Rect

보통은 Frame과 동일

➡️ alignmnetRectInset 오버라이딩 해라

💡frame, alignment rectangle은 일반적으로 다르지 않지만, 뱃지/그림자와 같은 효과가 추가된다면 달라진다.
Auto Layout은 alignment rectangle을 사용한다.
만약 위와 같은 체크박스를 frame 기준으로 view의 center로 맞춘다면 우리가 원하는 중앙에 배치되지 않고 약간 왼쪽으로 쏠리게 될 것이다.
따라서 alignment rectangle을 기준으로 Auto Layout을 적용한다.

참고자료

xcode menu -> Debug menu -> show Alignment Rect
or AlignmnetRectForFrame로 디버깅 모드에서 확인

Building the Layout

아래와 같이 레이아웃 엔진이 어떤 것이 포함되는지 볼 수 있다.

이러면 이제 원하는 레이아웃이 만들어지는 프로세스를 이해할 수 있다.

요약

profile
예비 iOS 개발자의 기록

0개의 댓글