Будет ли автоматически изменяться высота ячейки UITableView при изменении текста и констрейнтов
Что проверяют
Знаете ли вы, как работает self-sizing ячеек и что таблица сама по себе не следит за содержимым уже показанной ячейки. Следом обычно дают практический случай: ячейка с UITextView, которая должна расти по мере ввода.
Как отвечать
Короткий ответ: при первом показе да, при изменении содержимого видимой ячейки по умолчанию нет, пока таблице об этом не сказать. Исключение появилось в iOS 16, о нём ниже.
Чтобы высота считалась по содержимому:
- настройка таблицы:
rowHeight = UITableView.automaticDimensionи разумныйestimatedRowHeight. С iOS 11 self-sizing включён по умолчанию, но делегатtableView(_:heightForRowAt:)с фиксированным числом его перебивает; - констрейнты: непрерывная вертикальная цепочка от верхнего края
contentViewдо нижнего. Именно по ней Auto Layout вычисляет высоту; - многострочный текст: у
UILabelnumberOfLines = 0, уUITextViewisScrollEnabled = false, иначе у них нет собственной высоты.
Если текст или констрейнты поменялись у видимой ячейки, попросите таблицу пересчитать высоты: tableView.performBatchUpdates(nil) или старая пара beginUpdates() и endUpdates(). Ячейка при этом не пересоздаётся, клавиатура не прячется, изменение анимируется.
С iOS 16 у таблицы есть свойство selfSizingInvalidation. В режиме .enabled (он по умолчанию) ячейка пересчитывается, если вызвать у неё invalidateIntrinsicContentSize(), а режим .enabledIncludingConstraints сам замечает изменения констрейнтов внутри contentView.
Где спотыкаются
Привязывают элементы к самой ячейке, а не к contentView, или забывают нижний констрейнт. Высота берётся из оценки, а в консоли появляется предупреждение о неоднозначной высоте.
Обновляют высоту через reloadData() или reloadRows(at:with:). Ячейка пересоздаётся, UITextView теряет фокус, клавиатура прячется, а список прыгает.
Ставят estimatedRowHeight сильно меньше реального. При быстрой прокрутке таблица корректирует смещение на ходу, и контент дёргается. Помогает близкая к правде оценка или кэш посчитанных высот в tableView(_:estimatedHeightForRowAt:).