Ответ
Динамический расчет высоты ячейки основан на Auto Layout и системе вычисления размера контента. Вот основные методы:
1. Автоматический размер (iOS 8+, рекомендуемый) Самый простой способ, если ячейка использует Auto Layout.
// В viewDidLoad() таблицы
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 100 // Приблизительная высота для оптимизации
// Ячейка должна иметь однозначные (non-ambiguous) constraints
// от верхнего края contentView к нижнему.
// Для многострочного UILabel установите numberOfLines = 0.
Система сама вычислит высоту на основе констрейнтов.
2. Ручной расчет с systemLayoutSizeFitting (для сложных случаев) Используется, когда автоматического расчета недостаточно или нужен точный контроль.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// 1. Получаем экземпляр ячейки для расчета (не отображаемый)
let cell = tableView.dequeueReusableCell(withIdentifier: "YourCellID") as! YourCustomCell
// 2. Конфигурируем ячейку данными для конкретного indexPath
cell.configure(with: dataModel[indexPath.row])
// 3. Принудительно применяем layout
cell.setNeedsLayout()
cell.layoutIfNeeded()
// 4. Вычисляем требуемый размер
let targetSize = CGSize(width: tableView.bounds.width, height: UIView.layoutFittingCompressedSize.height)
let calculatedSize = cell.contentView.systemLayoutSizeFitting(
targetSize,
withHorizontalFittingPriority: .required, // Ширина фиксирована
verticalFittingPriority: .fittingSizeLevel // Высота подстраивается под контент
)
// 5. Возвращаем высоту + 1 пункт (часто для разделителя)
return calculatedSize.height + 1.0
}
3. Для UICollectionView (FlowLayout)
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
}
// Или задать точный размер через делегат
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// ... аналогичная логика расчета
}
Критически важные условия для работы:
- Констрейнты в ячейке должны быть полными и неконфликтующими.
- Должна существовать непрерывная цепочка constraints от верхнего до нижнего края
contentView. - Для многострочного текста у
UILabelдолжно бытьnumberOfLines = 0и установленcontentCompressionResistancePriority. - Используйте
estimatedRowHeightдля повышения производительности.
Совет: Для очень сложных или производительных списков рассмотрите UICollectionViewCompositionalLayout или фреймворк вроде IGListKit.