Dequeued UITableViewCell имеет неправильную компоновку до прокрутки (с использованием автозапуска)
У меня есть пользовательский подкласс UITableViewCell
, который имеет ограничения на автоопределение, применяемые к нему в Interface Builder. Ячейка содержит несколько видов, включая UITextField
.
Соответственно размер UITextField
ограничен таким, что между ним и следующим представлением существует горизонтальное расстояние по умолчанию.
Ячейка создается следующим образом:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"ProgressCell";
ProgressCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath]
cell.textField.text = @"Some string that is different for each cell";
return cell;
}
Когда ячейка сначала появляется, UITextField
переполняет правильный фрейм и появляется позади UIView
справа. Однако, когда я прокручиваю ячейку с экрана, приостанавливаю и затем прокручиваю назад, текст усекается правильно.
Пример показан ниже (во втором редактировании).
Я попытался позвонить [cell setNeedsLayout]
и [cell setNeedsDisplay]
для ячейки в cellForRowAtIndexPath
, а также выполнить их после задержки. Неэффективно.
Что такое прокрутка экрана, что вызывает корректность отображения ячейки, и как я могу либо ее реплицировать, либо исправить основную проблему?
EDIT:
Вызов
[self.tableView reloadData];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];
чтобы перезагрузить ячейку, кажется, что первый раз макет отображался правильно.
Однако теперь он прерывается (иногда) при прокрутке (т.е. при прокрутке назад, ограничения макета теперь не применяются правильно).
Вызов [cell setNeedsLayout]
в cellForRowAtIndexPath
не устраняет эту проблему.
EDIT2:
Верхняя ячейка, как показано на рисунке здесь, появилась правильно (как это делает нижняя ячейка), пока я не прокручу экран вниз. Он с тех пор исчез.
Это отражает проблему с первого редактирования - это второй рендеринг, который является проблемой (заставляет меня думать, что это может иметь какое-то отношение к повторному использованию ячейки?)
Ответы
Ответ 1
Если вы укажете свойство в подклассе UITableViewCell
textLabel
или defaultTextLabel
, тогда IB проигнорирует указанные вами ограничения и переопределит их по умолчанию, без предупреждений.
Это справедливо даже для ячеек, разработанных в IB с пользовательским стилем, которые не имеют видимых свойств textLabel
или detailTextLabel
.
Это также происходит, если добавить свойство свойства типа UIImageView
в подкласс UITableViewCell
и называть его imageView
.
Ответ 2
В соответствии с этим несколько строк UILabel
проблема GitHub, это затяжная ошибка iOS.
Я обнаружил, что в iOS 9+ эта ситуация в основном возникает в режиме редактирования с большой непредсказуемостью.
Приведенное ниже обходное решение работает только частично: оно требует повторного рисования UITableView
и все еще не охватывает все сценарии.
override func viewDidLoad() {
super.viewDidLoad()
tableView.setNeedsLayout()
tableView.layoutIfNeeded()
tableView.reloadData()
}
Примечания:
- Использование
UITextView
- отличная альтернатива нескольким строкам UILabel
без ошибок. UITextView
не отображает ни одну из IULabel
других странностей, например ошибки выравнивания или мерцание.
- Существует также альтернативное решение SO-25947146, которое не работает для меня, но стоит упомянуть.
- Кажется, что происходит заметно, когда
self.tableView.editing
true
- Использование низких значений для
tableView.estimatedRowHeight
уменьшает вероятность появления
- Демонстрация ошибки на SwiftArchitect/TableViewControllerRowHeightBug gist