Как сверстать self-sizing ячейку таблицы в iOS
Что проверяют
Понимаете ли вы, откуда таблица берёт высоту ячейки: из цепочки констрейнтов внутри contentView, а не из магии automaticDimension. Следом обычно спрашивают, как обновить высоту, если контент поменялся после показа, например догрузилась картинка.
Как отвечать
Настройка таблицы: rowHeight = UITableView.automaticDimension и разумный estimatedRowHeight. Оценка, близкая к реальной, делает точнее индикатор прокрутки и scrollToRow, а heightForRowAt не реализуют.
Вёрстка ячейки:
- всё внутри
contentView: сабвью добавляются туда, а не в саму ячейку, иначе ломаются отступы и swipe-действия; - непрерывная вертикальная цепочка: от верхнего края
contentViewчерез все элементы до нижнего. Если хотя бы одно звено разорвано, Auto Layout не может вычислить высоту; - многострочный текст:
numberOfLines = 0уUILabel, иначе метка останется в одну строку; - приоритеты: при двух метках в ряд настройте
setContentCompressionResistancePriorityиsetContentHuggingPriority, чтобы было ясно, какая из них переносится; - конфликт на первом проходе: таблица временно ставит свою высоту
UIView-Encapsulated-Layout-Height, и в консоли появляется конфликт. Нижний констрейнт с приоритетом 999 снимает этот шум.
Изменение высоты после показа. С iOS 16 у таблицы есть selfSizingInvalidation, и ячейка может сама запросить пересчёт через invalidateIntrinsicContentSize(). Классический способ: обновить данные и вызвать performBatchUpdates(nil) или пару beginUpdates() и endUpdates(), таблица пересчитает высоты с анимацией.
Где спотыкаются
Не замыкают цепочку до нижнего края: констрейнты есть сверху и по бокам, а снизу нет. Ячейка получает стандартную высоту, и кандидат ищет проблему в настройках таблицы.
Считают высоту вручную в heightForRowAt через boundingRect, дублируя логику вёрстки. Такой код расходится с ячейкой при первой смене шрифта или Dynamic Type.
Асинхронно подгружают картинку, меняют её размер и не сообщают таблице. Ячейка обрезает контент. Размер изображения лучше знать заранее из данных или задать фиксированным соотношением сторон.