iOS/Swift

heightAnchor랑 bottomAnchor는 뭐가 다를까?

밤새는 탐험가89 2024. 9. 6. 13:42
    let detailHeaderViewConstraints = [
        detailHeaderView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
        detailHeaderView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
        detailHeaderView.topAnchor.constraint(equalTo: contentView.topAnchor),
        detailHeaderView.heightAnchor.constraint(equalToConstant: 360),
        
        // 아래 코드를 넣어야 스크롤이 됨
        detailHeaderView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
    ]

 

🔥 detailHeaderView를 좌, 우, 상 그리고 높이를 지정했습니다. 하지만 무슨 이유인지 몰라 detailHeaderView 안에 있는 collectionView가 가로 방향으로 스크롤되지 않았습니다. 

 

detailHeaderView.bottomAnchor를 contentView.bottomAnchor에 연결함으로써 스크롤뷰의 내용 크기가 제대로 계산되어 문제를 해결한 것 같습니다.

이로 인해 스크롤뷰가 수직 방향으로 스크롤할 수 있는 충분한 컨텐츠 크기를 인식하게 되어, 스크롤이 제대로 작동하게 된 것입니다. 또한, 이 방식으로 하면 UIScrollView 내의 모든 콘텐츠가 자연스럽게 표시되고, 컬렉션 뷰의 가로 스크롤도 정상적으로 작동할 것입니다.

 

간단한 원리 설명

  • UIScrollView는 자식 뷰들의 크기와 제약 조건에 따라 **컨텐츠 크기(contentSize)**를 계산합니다. 이때, contentView의 하단 제약 조건이 설정되지 않으면, 스크롤뷰가 전체 컨텐츠의 높이를 제대로 계산하지 못해 스크롤이 되지 않는 경우가 발생합니다.
  • detailHeaderView.bottomAnchor를 contentView.bottomAnchor에 연결하면서 스크롤뷰는 이제 컨텐츠의 크기를 정확히 인식하게 되어, 스크롤 기능이 제대로 작동하게 된 것입니다.

요약

  • detailHeaderView의 하단 제약 조건을 설정해 줌으로써, 스크롤뷰의 컨텐츠 크기 계산 문제를 해결하셨습니다.
  • 이제 스크롤이 제대로 동작할 것이며, 컬렉션 뷰의 가로 스크롤도 함께 정상적으로 작동할 것입니다.

 

 

🔥 heightAnchor로는 높이 계산이 안되나?

 

⭐️ heightAnchor를 설정해도 스크롤이 안 되는 이유 ⭐️

heightAnchor를 설정했음에도 스크롤이 되지 않은 이유는 UIScrollView가 컨텐츠의 전체 크기를 계산하는 방식과 관련이 있습니다. 스크롤뷰는 자식 뷰들의 제약 조건을 통해 **컨텐츠 크기(contentSize)**를 자동으로 결정합니다. 그러나 이 과정에서 스크롤뷰는 뷰의 높이와 더불어 자식 뷰의 모든 제약 조건을 고려해야 합니다.

즉, 높이만 설정하는 것으로는 충분하지 않으며, 자식 뷰의 상하 제약 관계가 명확히 설정되어야 합니다.

핵심 원리: 스크롤뷰 내에서의 제약 조건 설정

  1. 스크롤뷰의 컨텐츠 크기 계산:
    UIScrollView는 내부에 추가된 모든 자식 뷰의 제약 조건을 종합해서 **컨텐츠 크기(contentSize)**를 자동으로 계산합니다.
    • 상단 앵커 (topAnchor)와 하단 앵커 (bottomAnchor)가 모두 설정되어야 스크롤뷰는 자식 뷰가 차지하는 전체 높이를 인식할 수 있습니다.
    • 만약 상단, 하단 제약 조건이 모두 설정되지 않으면 스크롤뷰는 자식 뷰가 얼마만큼의 높이를 차지해야 하는지 제대로 인식하지 못합니다.
  2. heightAnchor와 bottomAnchor의 차이:
    • heightAnchor는 자식 뷰의 고정된 높이를 설정하지만, 스크롤뷰는 그 높이가 화면 밖으로 벗어나도 자동으로 인식하지 않습니다. 이 때문에 **하단 제약 조건(bottomAnchor)**이 필요합니다.
    • bottomAnchor는 자식 뷰가 스크롤뷰의 하단까지 얼마큼 이어지는지 알려줍니다. 이 제약이 없으면, 스크롤뷰는 자식 뷰의 하단을 정확히 알지 못해 컨텐츠의 끝을 제대로 계산하지 못하고 스크롤이 되지 않게 됩니다.

 

예시 상황

let detailHeaderViewConstraints = [
    detailHeaderView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
    detailHeaderView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
    detailHeaderView.topAnchor.constraint(equalTo: contentView.topAnchor),
    detailHeaderView.heightAnchor.constraint(equalToConstant: 360)
]

 

이 코드에서 heightAnchor로 360의 높이를 설정했지만, 스크롤뷰는 자식 뷰의 끝을 알지 못하기 때문에 제대로 스크롤되지 않습니다. 상단 앵커(topAnchor)와 하단 앵커(bottomAnchor)가 둘 다 설정되어야, 스크롤뷰는 자식 뷰의 전체 크기를 알 수 있습니다.

이를 보완한 코드가 다음과 같습니다:

let detailHeaderViewConstraints = [
    detailHeaderView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
    detailHeaderView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
    detailHeaderView.topAnchor.constraint(equalTo: contentView.topAnchor),
    detailHeaderView.heightAnchor.constraint(equalToConstant: 360),
    detailHeaderView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) // 추가한 하단 제약 조건
]

 

이제 스크롤뷰는 detailHeaderView가 상단부터 하단까지 얼마만큼의 영역을 차지하는지 정확히 계산할 수 있게 되어 스크롤이 제대로 작동합니다.

 

요약

  • heightAnchor는 자식 뷰의 고정된 높이만 설정해 주지만, 스크롤뷰는 자식 뷰의 전체 범위를 알기 위해 상단과 하단 제약 조건이 모두 필요합니다.
  • 상하 제약 조건이 모두 설정되지 않으면, 스크롤뷰는 자식 뷰가 어디까지 있는지 알지 못해 스크롤이 되지 않습니다.
  • bottomAnchor를 추가함으로써 스크롤뷰는 자식 뷰의 전체 높이를 계산할 수 있게 되어 스크롤이 정상적으로 작동하게 됩니다.