#ios #swift #uitableview #ios-autolayout
#iOS #swift #uitableview #ios-автозапуск
Вопрос:
Я столкнулся с досадной ситуацией. Я нашел похожие вопросы, но ответы мне не помогли, поэтому я надеялся, что смогу получить какой-нибудь совет.
У меня есть пользовательская UITableViewCell, где я использую файл .xib. Я извлекаю некоторые данные при загрузке приложения, и как только они получены, я перезагружаю свой TableView. В ячейках отображается изображение и некоторые метки, и мне нужно, чтобы метки корректировали свой размер в зависимости от ширины текста для содержимого в отдельной ячейке. Скажем, у меня есть это для cellForRowAt indexPath
:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard
let cell = tableView.dequeueReusableCell(withIdentifier: MyCell.reuseIdentifier, for: indexPath) as? MyCell,
indexPath.row < myDataArray.count
else { return UITableViewCell() }
let dataForCell = myDataArray[indexPath.row]
cell.configure(with: dataForCell)
cell.layoutIfNeeded()
return cell
}
Теперь в моем MyCell.swift
файле внутри configure(with:)
метода я устанавливаю тексты меток, затем я также вызываю частный метод с именем setWidths()
, который использует расширение, которое я добавил к UILabel
, чтобы вернуть мне ширину метки после установки текста — я выполняю некоторые базовые вычисления, чтобы настроить ограничения меток так, как я хочу.
Единственная проблема, с которой я сталкиваюсь, заключается в том, что при первоначальной загрузке табличного представления ширина метки обновляется неправильно, но когда я прокручиваю вниз до ячеек, которые изначально были вне рамки, они отображаются правильно, а затем, когда я прокручиваю обратно до ячеек, которые изначально были в рамке и смещены, они также отображаются правильно.
Я знаю, что раньше сталкивался с подобными проблемами, но обычно вызов layoutIfNeeded()
ячейки устраняет проблему. На этот раз нет.
Я знаю, что это связано с идеей многократного использования ячеек и удаления из очереди, но почему первая группа ячеек размещена не по тем же правилам? Это первые ячейки, которые видит пользователь, мне нужно, чтобы они были правильными!
У кого-нибудь есть какие-либо советы для меня?
Редактировать
Я думаю, что я нацелился на проблему, однако я все еще не совсем знаю, что делать. Я должен скорректировать рассчитанную ширину метки на основе доступной с рамки ячейки. Я добавил несколько операторов печати, чтобы увидеть, изменилась ли ширина ячейки, и это так. Внутри setWidths()
метода, который я добавил print(self.frame.width)
, и при первой загрузке TableView он распечатывается 325.0
для каждой ячейки, но затем, когда я прокручиваю и он выделяет новые ячейки, он меняется на 414.0
(с использованием симулятора iPhone 8 Plus). Что вызывает изменение ширины рамки ячейки от первоначального макета до повторного использования ячейки?
Комментарии:
1. Почему бы вам просто не установить свои ограничения и использовать UITableViewAutomaticDimension вместо того, чтобы вычислять размер самостоятельно?
2. @LuisPerez — Я использую автоматическое измерение высоты каждой ячейки, но я не могу использовать его для ширины этих отдельных меток. У меня есть очень специфический макет, которому я должен следовать, где метки должны сжиматься в зависимости от доступного пространства для соседних меток. Это слишком сложно объяснить здесь, не просто сбивая всех с толку. Я добавил правку к своему вопросу, которая позволяет мне узнать, что происходит.
3. Думаю, теперь я понимаю, что в тот момент, когда вы вычисляете ширину своей ячейки, contentView еще не отображается, что вам нужно сделать, это изменить свой метод configure, чтобы использовать ширину, и туда вы можете отправить ширину рамки tableview, это будет что-то вроде этого:
cell.configure(with: DataForCell, width: tableview.frame.width)
Редактировать: после этого используйте эту ширину для вычисления размера надписей4. @LuisPerez — Да, вы правы. Я просто попытался добавить операторы печати в
viewDidLoad
, а затем еще раз вcellForRowAt
— по какой-то причине вviewDidLoad
моемself.view.frame.width = 375.0
, но затем вcellForRowAt
theself.view.frame.width = 414.0
, что делает мою математику правильной. Если вы хотите добавить ответ, я приму его. Итак, iOS просто настраивает общий размер фрейма? Почему произошла смена с375.0
на414.0
? Вот чего я просто не понимаю
Ответ №1:
Проблема здесь в том, что вы вычисляете свои размеры, когда ячейка еще не отрисована, обновите свой метод configure, чтобы использовать ширину tableview, вот так cell.configure(with: DataForCell, width: tableview.frame.width)
, после этого используйте эту ширину для настройки ваших размеров, и о том, почему она меняется с 375 на 414, ответ заключается в том, что вы получаете ширину обычного iphone, при отрисовке вида он меняется на plus size.
Комментарии:
1. @LuizPerez — Я также допустил глупую ошибку в своих расчетах, которую я только что осознал, на случай, если у кого-то еще есть подобная проблема. Прежде чем я рассчитал изменение ширины для одного ограничения, я изменил ширину другой метки на основе размера ее текста, и в своих расчетах я использовал
otherLabel.frame.width
вместо своего IBOutletotherLabelWidthConstraint.constant
. Итак, в моих расчетах использовался фрейм другой метки (который еще не изменился и был настроен на то, как его константа была расположена в файле XIB), вместо того, чтобы использовать ширину, на которую я ее изменил, но она еще не обновлялась.