Written on 2025–04–20

在本文當中想要分享一些在 UITableViewCell 當中使用 auto layout 發生的一些事情。

我們都知道在自定義的 UITableViewCell 當中如果想要保有與系統相同的內部間距可以在 auto layout 當中透過 contentView.layoutMarginsGuide 來設定 layout constraint。

當我們想要自定義 cell 並且希望移除系統自帶的分割線同時希望兩個 cell 之間有間距的話就可以採用在 contentView 裡面再包一個 UIView,並且這個 UIView 的 bottomAnchor 與 contentView 有一段距離。

此時如果我們想要在這個當中添加想要的 UIView 並且想要明確給定高度時,我們會直覺的使用以下的 constraint。

NSLayoutConstraint.activate([
    subview.topAnchor.constraint(equalTo: view.topAnchor, constant: 12),
    subview.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    subview.widthAnchor.constraint(equalToConstant: 40),
    subview.heightAnchor.constraint(equalToConstant: 40),
    subview.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -12)
])

如果依照以上的 constraint 執行,就會直接發生 Encapsulated-Layout-Height 上的錯誤。

這是因為我們指定了 [top, bottom, height] 三個限制,此時 cell 的高度是明確的並且是寫死的,這樣會導致 cell 在創建時系統會先給一個預設的高度時發生錯誤,最終出現 constraint 問題。

正確的作法應該是以下方式。

NSLayoutConstraint.activate([
    subview.topAnchor.constraint(equalTo: view.topAnchor, constant: 12),
    subview.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    subview.widthAnchor.constraint(equalToConstant: 40),
    subview.heightAnchor.constraint(equalToConstant: 40),
    subview.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor, constant: -12)
])

最關鍵的地方是在調整 bottomAnchor 的 layout constraint,在這裡我們應該使用 lessThanOrEqualTo ,這樣 cell 的高度在一開始就不會是寫死的,並且會在系統創建 cell 後自動調整高度。