Вы сталкиваетесь с побочным эффектом новой фантастической функции в iOS8 Tableviews: Automatic Row Heights.
В iOS 7 у вас либо были строки фиксированного размера (заданные с помощью tableView.rowHeight
), либо вы написали код для вычисления высоты ваших ячеек и вернули бы его в tableView:heightForRowAtIndexPath
. Написание кода для вычисления высоты ячейки могло бы быть довольно сложным, если бы у вас было множество представлений в вашей ячейке и у вас были разные высоты, которые нужно учитывать при разных размерах шрифта. Добавьте динамический тип, и процесс оказался занозой в заднице.
В iOS 8 вы по-прежнему можете делать то же самое, но теперь iOS может определять высоту строк при условии, что вы настроили содержимое ячейки с помощью Auto Layout. Это огромное преимущество для разработчиков, поскольку при изменении размера динамического шрифта или изменении размера текста пользователем с помощью настроек специальных возможностей пользовательский интерфейс может адаптироваться к новому размеру. Это также означает, что если у вас есть UILabel, который может иметь несколько строк текста, ваша ячейка теперь может увеличиваться, чтобы вместить их, когда это необходимо ячейкам, и сжиматься, когда это не так, поэтому нет ненужных пробелов.
Предупреждающее сообщение, которое вы видите, сообщает вам, что в вашей ячейке недостаточно ограничений для автоматического макета, чтобы сообщить табличному представлению о высоте ячейки.
Чтобы использовать динамическую высоту ячейки, которая, наряду с методами, уже упомянутыми в других плакатах, также избавит от этого сообщения, вам необходимо убедиться, что ваша ячейка имеет достаточные ограничения для привязки элементов пользовательского интерфейса к верхней и нижней части ячейки. Если вы раньше использовали Auto Layout, вы, вероятно, привыкли устанавливать ограничения Top + Leading, но для динамической высоты строки также требуются ограничения снизу.
Этап макета работает так, что происходит непосредственно перед отображением ячейки на экране точно в срок:
Рассчитываются размеры содержимого с внутренними размерами. Это включает UILabels и UIImageViews, где их размеры основаны на тексте или UIImages, которые они содержат, соответственно. Оба этих представления будут считать свою ширину известной (потому что вы установили ограничения для задних / передних кромок, или вы установили явную ширину, или вы использовали горизонтальные ограничения, которые в конечном итоге показывают ширину из стороны в сторону). Допустим, у метки есть абзац текста («количество строк» установлено на 0, поэтому он будет автоматически переноситься), он может быть только 310 точек в поперечнике, поэтому он определен как высотой 120 пунктов при текущем размере шрифта.
Пользовательский интерфейс размещен в соответствии с вашими ограничениями позиционирования. В нижней части метки есть ограничение, которое соединяется с нижним полем ячейки. Поскольку метка выросла до 120 точек в высоту, и поскольку она привязана к нижней части ячейки ограничением, она должна подтолкнуть ячейку «вниз» (увеличивая высоту ячейки), чтобы удовлетворить ограничение, которое гласит «нижняя часть метка всегда находится на стандартном расстоянии от низа ячейки.
Сообщение об ошибке, о котором вы сообщили, возникает, если это нижнее ограничение отсутствует, и в этом случае нет ничего, что могло бы "отодвинуть" нижнюю часть ячейки от верхней части ячейки, что является сообщением двусмысленности: нечего толкать нижнюю часть из вверху ячейка разрушается. Но Auto Layout тоже обнаруживает это и возвращается к использованию стандартной высоты строки.
Что бы это ни стоило, и в основном для получения округленного ответа, если вы действительно реализуете динамическую высоту строк на основе автоматического макета iOS 8, вам следует реализовать tableView:estimatedHeightForRowAtIndexPath:
. Этот метод оценки может использовать приблизительные значения для ваших ячеек, и он будет вызываться при первоначальной загрузке табличного представления. Это помогает UIKit рисовать такие вещи, как полоса прокрутки, которую нельзя нарисовать, если табличное представление не знает, сколько контента оно может прокручивать, но не требует абсолютно точных размеров, поскольку это просто полоса прокрутки. Это позволяет отложить вычисление фактической высоты строки до момента, когда ячейка понадобится, что требует меньших вычислительных затрат и позволяет быстрее представить ваш UITableView.