[AutoLayout] IntrinsicContentSize, Hugging/Compression Priority

숑이·2023년 8월 26일
1

AutoLayout

목록 보기
1/1
post-thumbnail

이번에는 그동안 미루고 있던 AutoLayout에 대해 공부를 하려고 합니다.
Constraints를 통해 AutoLayout을 사용하는 것에는 문제가 없지만, 그동안 IntrinsicContentSize나 Priority 등의 이해 없이 무식하게 AutoLayout을 사용한 것 같아서 오늘 제대로 이해해보는 시간을 갖겠습니다.

IntrinsicContentSize

뷰에서 자기 자신이 표현해야 할 콘텐츠의 '자연스러운' 크기

IntrinsicContentSize는 UIView의 서브클래스 중 일부가 가지는 속성으로, 뷰에서 자기 자신이 표현해야 할 콘텐츠의 자연스러운 크기를 나타냅니다.
이 크기는 Autolayout 시스템에서 사용되어 뷰의 크기를 결정하는데 도움이 됩니다.

예를 들어, UILabel이나 UIButton 같은 클래스는 내부에 표시할 텍스트에 따른 적절한 크기를 계산해서 IntrinsicContentSize로 제공합니다.

스토리보드에 UILabel을 놓고, Top, Leading에 Constraint 설정했습니다.
width, height는 따로 설정하지 않았지만, UILabel은 IntrinsicContentSize를 제공하기 때문에 오류가 발생하지 않습니다.

이번엔 UIView를 놓고, 마찬가지로 Top, Leading에만 Constraint를 설정했습니다.
그런데, 이번에는 오류가 발생합니다.

UILabel과 똑같은 조건인데 Label은 오류가 발생하지 않고, UIView는 오류가 발생하네요?
왜 그럴까요?

UIView는 콘텐츠가 없기 때문에 기본적인 크기도 존재하지 않습니다.
오류를 해결하기 위해서는 UIView의 크기를 지정해주면 되겠죠?

이렇게 고유 콘텐츠가 포함된 UI들은 콘텐츠의 크기에 따라 자동으로 View의 Size가 계산되어 적용되고, 고유 콘텐츠가 없는 UI는 Size가 자동으로 적용되지 않기 때문에 크기에 대한 조건을 명시해야합니다.

Hugging & Compression Resistance Priority

고유 사이즈가 있는 View 들 사이에는 그 View들 중에서 어떤 녀석이 고유 사이즈를 지키고, 어떤 녀석이 줄어들고, 늘어나야하는지를 결정하는 우선순위가 존재합니다.
그 우선순위를 결정하는 것이 Hugging Priority, Compression Resistance Priority 입니다.

결론부터 먼저 말하면,

Hugging 우선순위가 높으면, 고유 사이즈보다 커지지 않으려하고,
Compression 우선순위가 높으면, 고유 사이즈보다 작아지지 않으려합니다.

이 두가지만 외우면 어렵지 않습니다.

스토리보드에 label과 button을 두고, StackView로 묶어서 StackView를 Y축 정렬, 왼쪽, 오른쪽으로 10만큼 Constraints를 설정했습니다.

Label과 Button은 Intrinsic Content Size가 있고, StackView의 영역을 채우기에는 크기가 작기 때문에 두 View 중에서 하나는 남는 영역을 채워야 합니다.

UILabel은 고유 사이즈를 지켰고, Button은 고유 사이즈보다 더 크게 늘어났죠?
UILabel의 Hugging 우선순위가 더 높기 때문에. 즉, label이 고유 사이즈보다 커지지 않으려하기 때문에 Hugging 우선순위가 더 낮은 Button이 늘어났다고 예측할 수 있습니다.

실제로 그런지 인터페이스 빌더에서 확인해보겠습니다.

Label은 Horizontal Hugging Priority가 251이고, Button은 250이죠?

위에서 예측한 것이 맞았네요.

그런데 보통 이런 UI를 구성할 때, 버튼을 늘리기 보다는 Label을 늘려서 Button의 사이즈를 유지하는게 더 보기 좋아보일 것 같습니다.

Button을 늘리지 않고, Label이 늘어나게 하려면 어떻게 해야할까요?

Button의 Hugging Priority를 Label보다 높여주면 되겠죠?
아니면, Label의 Hugging Priority를 낮춰도 될거에요.

이렇게 고유 사이즈보다 커지지 않으려는 성질의 우선순위를 결정하는 것이 바로 Content Hugging Priority 입니다.

여기까지 이해 됐으리라 생각하고, 이제 Compression Priority에 대해서 알아볼게요!

이렇게 Label의 Text에 아주 긴~ Text가 들어갔다고 해볼게요.

그런데 이런 오류가 발생하네요?

horizontal compression resistance를 감소시키라고 알려주고 있습니다.
이 값이 감소하면, 어떤 일이 발생할까요?

위에서 compression resistance는 고유 사이즈보다 작아지지 않으려는 성질이 있다고 했죠?
그런데 이 값을 감소시키면, 우선순위가 낮아지게 되고, 결국 고유 사이즈보다 작아지겠죠? 즉, 콘텐츠가 잘려서 보이게됩니다.

현재 horisontal Compression Resistance Priority가 Label과 Button 모두 750으로 동일합니다. 이 경우에는 Label과 Button 중 어떤 View가 작아져야하는지 모르기 때문에 충돌이 발생한 것 입니다.

이를 해결하기 위해서 Button의 Compression Resistance Priority를 높여보겠습니다.

Button의 Compression Resistance 우선순위가 Label보다 높기 때문에. 즉, Button은 고유 사이즈보다 작아지지 않으려는 성질의 우선순위가 Label보다 높기 때문에 Button의 크기를 유지하고, Label의 크기가 고유 사이즈보다 작아져서 콘텐츠가 잘려보이게 됐습니다.

반대로 Label의 고유 사이즈를 유지하고, Button을 작아지게 하려면 어떻게 해야할까요?

이렇게 Label의 Compression Priority를 Button보다 크게 설정해주면 되겠죠?

하지만, 일반적으로 UI를 구성할 때 Button의 Compression Priority를 높게 설정하는 것이 더 보기 좋을 것 같네요.

최종 정리

  • IntrinsicContentSize는 고유 콘텐츠가 존재하는 View의 크기를 자동으로 계산한다.
  • 허깅은 고유 사이즈보다 커지지 않으려고 하는 조건이다.
  • 컴프레션은 고유 사이즈보다 줄어들지 않으려고 하는 조건이다.
profile
iOS앱 개발자가 될테야

0개의 댓글