Ios 8 Подробный текст UITableViewCell не корректно обновляется
Изменить: tl; dr: Могу ли я заставить detailTextLabel обновлять свой размер с помощью системы автоматического макета в iOS при изменении значения?
Edit2: У меня есть частичное решение, но продолжу поиск лучшего. См. Ниже.
У кого-нибудь еще были проблемы с меткой detailText в UITableViewCell с iOS 8?
У меня есть таблица, которая содержит как текстовые, так и подробные строки. Первоначально подробный текст представляет собой пустую строку (@""). После выполнения сериала раскадровки на экране редактирования я возвращаюсь с новым значением для подробного текста и обновляю его. Я пытаюсь перезагрузить таблицу в viewWillAppear, чтобы значение было сразу же после возврата к предыдущему виду.
Когда вид таблицы снова виден, ячейка таблицы сдвинула текстовое поле вверх, чтобы освободить место для подробного текста, но не отображается подробный текст. Текст не отображается, пока я не вернусь на экран редактирования и не вернусь второй раз.
Что я сделал для устранения неполадок: Похоже, что макет автоматической компоновки для текстовой метки детали не корректно обновляется, как я думаю, и должен регистрировать размер и состав detailTextLabel кадр подтверждает это.
Я могу заставить текст обновить, запустив [table reloadData] в viewDidAppear, однако это оставляет меня с мерцающим эффектом, который мне не нравится, и выглядит непрофессиональным.
Изменить: дополнительные действия, которые я сделал: я также заставил detailTextLabel перестраивать себя, используя [cell.detailTextLabel sizeToFit]. Это заставляет его отображать, но смещается в ячейке нечетным образом. После того, как вы снова перейдете на страницу редактирования, detailTextLabel зафиксирует ее положение.
Я создал простой проект как репозиторий github, чтобы точно показать, что я имею в виду:
https://github.com/acidaris/ios8_table_issue
Основной код контроллера просмотра, который я использую, также находится ниже.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.table reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
cell.textLabel.text = @"This is a test";
cell.detailTextLabel.text = self.value;
CGRect frame = cell.detailTextLabel.frame;
NSLog(@"detailTextLabel x=%f y=%f width=%f height=%f",
frame.origin.x,frame.origin.y,frame.size.width,frame.size.height);
return cell;
}
Ячейка прототипирована в StoryBoard, и поэтому ячейка, выбранная dequeueReusableCellWithIdentifier: всегда определяется. Кроме того, тип ячейки в раскадровке установлен на субтитры, и он отображает, если определено начальное значение.
Если бы кто-нибудь мог помочь мне понять это, я был бы невероятно благодарен.
Частичное решение
Если вы подклассифицируете UITableViewCell, вы можете изменить кадр для detailTextLabel, когда макет будет выполнен. Это то, что я сделал, и, похоже, сработал, , но на 6 плюс я получаю странную разделительную линию между textLabel и detailTextLabel. edit: (Я скорректировал это. ) Мне не нравится это решение, но пока это лучшее, что я встретил. Он не обновляется после представления представления и относительно прост. Как я сказал выше, я продолжу искать лучшее решение.
- (void)layoutSubviews {
[super layoutSubviews];
CGRect textFrame = self.textLabel.frame;
[self.detailTextLabel sizeToFit];
CGFloat x = textFrame.origin.x;
CGFloat y = textFrame.origin.y + textFrame.size.height;
CGSize detailSize = self.detailTextLabel.frame.size;
CGRect newFrame = CGRectMake(x, y, detailSize.width, detailSize.height);
self.detailTextLabel.frame = newFrame;
}
Я также обновил свой проект Github, чтобы отразить свое текущее решение. Edit3: Это не работает отлично, поскольку у него неправильные значения для действительно автоматических макетов, но он работает для моих целей на данный момент.
Изменить 4: я обновил функцию layoutSubviews, чтобы сделать ее более умной. Он будет иметь размер, чтобы зафиксировать содержимое в метке и поместить метку соответствующим образом в координатах x/y относительно текстовой метки.
Ответы
Ответ 1
С той же проблемой. Мое решение состояло в том, чтобы вызвать [cell layoutSubviews]
, прежде чем возвращать ячейку в конце -tableView:cellFForRowAtIndexPath
. Это работает для меня, и я не счел нужным переопределять layoutSubviews
в подклассе ячейки.
Ответ 2
У меня такая же проблема, когда ячейка не обновляется правильно при использовании segue в раскадровке.
Пробовал
[setNeedsLayout] and [layoutIfNeeded]
в представлении и в представлении таблицы, и он НЕ работает.
[self.tableView reloadData] is in viewDidAppear, as it should.
Затем я попробовал совет от pixbug, и он сработал. Но НЕ следует использовать [layoutSubviews] напрямую. Поэтому я попробовал те, которые рекомендованы документами в ячейке вместо tableView или представления.
Пробовал
[cell setNeedsLayout]
но это НЕ работало.
Пытались
[cell layoutIfNeeded]
это РАБОТАЕТ для меня.
Я положил это перед возвратом ячейки.
Ответ 3
У меня была такая же проблема в раскадровке iOS 8 (без автоматической компоновки).
У меня был вид таблицы со статической ячейкой просмотра таблицы внизу. В IB я добавил некоторые пробелы в область содержимого ячейки таблицы (Стиль: "Правая деталь" ). Затем в коде (ViewDidLoad) я обновил содержимое ячейки с помощью...
self.copyrightsCell.detailTextLabel.text = @"<a string>";
Без пробелов IB ячейка была НЕВИДИМО в портретном режиме.
Но с начальными пробелами содержимое ячейки позже отображается правильно.
Надеюсь, это поможет кому-то.
Ответ 4
У меня такая же проблема.
Я уверен, что данные доступны и назначаются cell.detailTextLabel.text
Я заметил, что после того, как значение было назначено, нет мерцания, если значение изменяется при возврате в tableView.
Поэтому мне кажется, что есть только проблема при первом присваивании значения detailTextLabel.
Ответ 5
Итак, я последовал за этим шагом и многими другими. Это привело меня к тому, что кажется правильным ответом. Надеюсь, это поможет другим, так как это сбило меня с ума, так как iOS 7/8 внес какие-то изменения.
Мой ответ заключался в том, чтобы поместить обычный код обработки в viewWillAppear и добавить этот [self.tableview layoutSubviews] вместо [self.tableView reload data]. Я думаю, что это связано с тем, что Apple делает вещи более контролируемыми в iOS 7/8. Я ударил эту идею, просмотрев некоторую информацию о работе ячеек.
Опять же, я надеюсь, что это поможет другим решить эту неприятную проблему.
Ответ 6
Я думаю, что если вам нужно перезагрузитьData, это означает, что данные таблицы не загружаются при его создании.
Вам просто нужно будет загрузить ваши данные в viewdidload (или где-нибудь еще, до того, как представление таблицы получит свои данные), где находится ваше табличное представление, и затем соответствующим образом создать ячейки.
Обычно я просто использую массив любого объекта, который я использую, а затем использую [array objectAtIndex:indexpath.row]
, о котором вы, вероятно, знаете.
Кроме того, в предыдущем абзаце есть незавершенное предложение, которое выглядит важным.
Ответ 7
Подтверждение проблемы с помощью Xcode 6.3.2 (6D2105) OS X Yosemite 10.10.3
Я удостоверился, что правильное значение было назначено, но в первый раз нет шоу,
второй раз шоу.
cell.layoutSubviews() казался логичным для меня, так как казалось, что в представлении не было обновления, а добавление layoutSubviews() делало трюк.
Ответ 8
У меня была аналогичная проблема со статическим UITableView. Я меняю текст ярлыка, и он не обновляется на экране, если я не щелкнул по ячейке или не сделал ничего, чтобы принудительно обновить его представления.
Мое обходное решение состояло в том, чтобы вызвать после обновления текста:
tableView.reloadData()
P.S Это не имеет никакого смысла; потому что это статический вид таблицы, и я не знаю, почему это сработало, но это было!