도니의 iOS 프로그래밍 세상

[UIKit] IntrinsicContentSize - 1탄 기초편 본문

UIKit

[UIKit] IntrinsicContentSize - 1탄 기초편

Donee 2023. 1. 2. 09:00

IntrinsicContentSize

IntrinsicContentSize는 Intrinsic(본래 갖추어진) + Size => 본래 갖추어진 사이즈를 의미합니다.
애플 문서에서의 정의를 볼까요?

View 자체의 속성만을 고려한 view의 자연스러운 사이즈를 의미합니다.

따라서, View들은 자체 속성만을 고려한 "타고난" 사이즈가 존재한다고 이해하시면 좋습니다.
이는 매우 중요한 개념인데요, 타고난 크기가 존재한다는 것만으로도 우리는 별도로 처리해야할 일들이 적어집니다.
어떤 일들이 줄어드는지 밑에서 확인하겠습니다.

IntrinsicContentSize를 갖거나, 갖지 못하는 것들

UIKit에서는 많은 View종류들이 존재합니다.(UITextView, UILabel, UITextField, UIView)
이런 View를 띄우게 됐을 때 Autolayout에서 어떤 것들은 오류창이 나타나고, 어떤 것들은 나타나지 않습니다.
한번 띄어보겠습니다.

Autolayout으로 UILabel과 UIView에 모두 leading과 top은 0, trailing은 >=20 을 주었습니다.

UILabel에서는 정상적으로 동작하고, UIView에서는 에러를 발생시켰습니다.

왜그럴까요?

발생원인

IntrinsicContentSize를 갖고 있다면, Autolayout만 조정함으로도 Swift에서는 해당 크기를 미리 알 수 있습니다.

만약 갖지 못한다면 Swift에서는 인식할 수 없으니, 경고창을 통해서 크기를 알려달라고 요청하는 것이지요.

결국 기본적으로 내장된 크기가 있는지, 없는지에 따라서 Swift는 해당 크기를 미리 알수 있고 없고가 결정됩니다.

그리하여 우리는IntrinsicContentSize가 있는 것들은 autolayout을 설정해도 위치를 지정하고 크기를 설정하는게 가능합니다.(하지만, 이런 경우에도 우선순위에 따라서 에러가 발생할 수 있습니다. 응용편에서 해당 예시를 자세하게 다루겠습니다.)
하지만 IntrinsicContentSize를 가지지 못한 것들은 그럼에도 불구하고 기본 사이즈가 존재하지 않기 때문에 height까지 확정 지어줄 필요가 있습니다.
또한, UIView가 trailing이 20보다 크거나 같다고 했을때, UIView는 기본 width가 존재하지 않기 때문에 Swift는 width를 결정지을 수 없습니다.
따라서, Swift에서는 width에 대해서도 확정적인 값을 결정할 수 있도록 조건을 수정해달라고 요청합니다.
그리하여 trailing을 0으로 고정하고, bottom Anchor도 수정함으로써 에러가 해결됩니다.

IntrinsicContentSize의 유무 확인(샘플 코드)

let viewTest = UIView()
    let label = UILabel()
    let stackView = UIStackView()
    let textField = UITextField()
    override func viewDidLoad() {
        super.viewDidLoad()
        // label.text = "11"
         // label은 내부 텍스트가 존재할 시 크기가 커짐
        [viewTest, label, stackView, textField].forEach { view in
            print(type(of: view), view.intrinsicContentSize)
        }

                // Output
//            UIView (-1.0, -1.0)
//            UILabel (0.0, 0.0) or UILabel(15.0, 20.3333333) => Text 있을 때 없을 때
//            UIStackView (-1.0, -1.0)
//            UITextField (5.0, 22.0)
    }

IntrinsicContentSize가 (width: -1, height: -1)이라면 존재하지 않는 것입니다.
그외에는 IntrinsicContentSize를 가지는 것들이 됩니다.
따라서 UILabel과 UITextField는 IntrinsicContentSize를 가지게 되고 UIView와 UIStackView는 갖지 못하게 됩니다.

IntrinsicContentSize가 중요한 이유

결과적으로 IntrinsicContentSize가 중요한 이유는 크게 두가지로 생각됩니다!

  • 해당 사이즈를 가지지 못한 UI들이 Autolayout만을 가질때 Ambiguous size error issue가 가장 많이 발생합니다.
  • IntrinsicContentSize를 가진 UI들은 서로간의 우선순위 문제가(hugging priority, conflict resistance) 발생합니다.
    첫번째 예시는 이번 글에서 다루었는데요, 두번째 이유는 무엇일까요?다음 포스팅에서는 Autolayout을 조정하면서 발생하는 hugging priority, conflict resistance에 대해 알아보겠습니다

결론

IntrinsicContentSize는 View가 가지는 고유의 사이즈를 말한다.
IntrinsicContentSize가 존재하는 것과 존재하지 않는 것은 Autolayout 지정시 별도로 달라지는 것들이 존재한다.

Comments