관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] systemLayoutSizeFitting 개념 (#AutoLayout 설정 후 바로 크기 알아내는 방법, #layoutFittingCompressedSize, #layoutFittingExpandedSize) 본문

iOS 응용 (swift)

[iOS - swift] systemLayoutSizeFitting 개념 (#AutoLayout 설정 후 바로 크기 알아내는 방법, #layoutFittingCompressedSize, #layoutFittingExpandedSize)

jake-kim 2023. 9. 10. 00:35

systemLayoutSizeFitting 개념

  • 오토 레이아웃 안에서, 현재 systemLayoutSizeFitting을 호출하는 뷰의 내부 크기를 계산한 결과를 반환해주는 함수
    • AutoLayout은 보통 동적으로 크기가 정해지고 나서 layoutSubivews()와 같은 델리게이트 메소드에서 frame.size를 알 수 있지만 systemLayoutSizeFitting을 사용하면 autoLayout 기반으로 잡힌 구조에서 크기를 바로 구할 수 있음

  • 파라미터에는 보통 2가지의 상수값을 사용
    • UIView.layoutFittingCompressedSize
    • UIView.layoutFittingExpandedSize

크기 옵션

  • layoutFittingCompressedSize
    • 레이아웃 시스템에게 뷰의 내용을 가능한 한 압축된 크기로 계산을 요청하여 뷰의 내용에 맞게 최소 크기를 계산
    • 뷰의 최소 크기를 계산할 때 사용
    • ex) UILabel 포함된 셀의 경우, 내용이 많이 들어가지 않을 때 사용
  • layoutFittingExpandedSize
    • 레이아웃 시스템에게 뷰의 내용을 가능한 한 확장된 크기로 계산 요청하여 뷰가 내용을 모두 수용하도록 크기가 조정
    • 뷰의 최대 크기를 계산할 때 사용
    • ex) UIlabel, UIImageView와 같이 내용을 충분히 표시하려면 확장된 크기가 필요한 경우에 사용

layoutSubivews() 없이 바로 크기 알아내는 방법

예제로 사용할 뷰 준비)

  • 위에서 설명했듯이, viewDidLoad 안에서 autoLayout을 설정하고 바로 view의 frame을 프린트해보면 적용이 안된 상태
override func viewDidLoad() {
    super.viewDidLoad()
    
    let label = UILabel()
    label.text = "iOS 앱 개발 알아가기"
    
    let button = UIButton()
    button.setTitle("button", for: .normal)
    
    view.addSubview(containerView)
    containerView.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        containerView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        containerView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    ])
    
    containerView.addSubview(label)
    NSLayoutConstraint.activate([
        label.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
        label.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
        label.topAnchor.constraint(equalTo: containerView.topAnchor),
    ])
    
    containerView.addSubview(button)
    NSLayoutConstraint.activate([
        button.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
        button.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
        button.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
        button.topAnchor.constraint(equalTo: label.bottomAnchor, constant: 8),
    ])
    
    print(containerView.frame) // <- .zero
}
  • 하지만 systemLayoutSizeFitting을 사용하면 위 타이밍에서도 autoLayout기반으로 내부적으로 계산하여 autoLayout이 적용되었을때의 크기 파악이 가능
print(containerView.frame) // .zero
print(containerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)) // (143.0, 62.333333333333336)
  • layoutSubviews()에서도 frame.size를 출력해보면 위에서 systemLayoutSizeFitting값과 동일
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    print("viewDidLayoutSubviews:", containerView.frame.size)  // (143.0, 62.333333333333336)
}

정리

  • AutoLayout으로 설정한 다음 뷰의 크기를 알고 싶을때 보통 layoutSubviews()에서 구하지만 다른 방법도 존재
  • systemLayoutSizeFitting 을 사용하면 굳이 layoutSubviews()에서 크기를 구할 필요가 없어져서 간결하게 크기를 구할 수 있음

* 전체 코드: https://github.com/JK0369/ExSystemLayoutSizeFitting

* 참고

https://developer.apple.com/documentation/uikit/uiview/1622624-systemlayoutsizefitting

Comments