UITableViewCell контент мерцает при перезагрузке ячеек по отдельности

У меня есть табличное представление, связанное с NSFetchedResultController (т.е. загрузка данных, а также отслеживание изменений в данных привязано к FRC)

Я не пользуюсь AutoLayout в моих клетках (из-за огромного падения производительности это вводит в iOS 8). Я выкладываю содержимое своих клеток вручную в ячейках (используя -(void)layoutSubviews). Кроме того, высота строк рассчитывается на основе содержимого и должным образом кэшируется / аннулируется.

Если какое-либо условие, связанное с моими данными, изменяется, связанные ячейки обновляются индивидуально (с целым -(void)controllerWillChangeContent:... через -(void)controllerDidChangeContent:... реализованы методы делегата) анимация для обновления строки: UITableViewRowAnimationNone

Проблема здесь в том, что мои ячейки имеют прозрачный фон, и я вижу некоторый визуальный шум (скорее всего, фактическая ячейка растягивается вертикально, я не могу сказать наверняка, потому что они действительно кратковременны и недолговечны) во время [self.tableView reloadRowsAtIndexPaths:...];,

Я перепробовал много вещей безрезультатно!

Вот то, что я попробовал, но это не работает:

  • Внедрение -(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath, возвращая точное значение для предполагаемой высоты.
  • установка self.tableView.rowHeight=UITableViewAutomaticDimension;, очень помогает, но не исправляет это.
  • Отключение анимации при [self.tableView beginUpdates]; и включение после [self.tableView endUpdates];
  • Удаление всех подпредставлений из содержимого ячеек в -(void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

Вещи, которые немного помогают:

  • Создание непрозрачных ячеек (т.е. установка цвета фона для ячеек). как ни странно, артефакты, кажется, находятся под фактическим содержанием клетки.

Больше информации

  • Большинство содержимого моих ячеек являются узлами из AsyncDisplayKit (ASTextNode, ASImageNode), но заменяют их своими UIKit коллеги не решают проблему.
  • Все мои визуальные обновления происходят в главном потоке. Я всегда в этом уверен.
  • Проблема не вездесуща, но существует чаще, чем нет. Похоже, они происходят чаще после того, как вставлены вторые клетки, если это помогает
  • Регистрация метода -(void)layoutSubviews в моих ячейках видно, что ячейки с условием обновления перезагружаются 3 раза подряд при каждом обновлении, в отличие от других ячеек, которые обновляются только один раз. Я не заставляю [cell layoutIfNeeded]; или же [cell setNeedsLayout]; в любом месте.
  • Перезагрузка всей таблицы с помощью [self.tableView reloadData]; это не вариант для меня.

Дополнительная информация

  • Создание непрозрачных клеток приводит к тому, что клетки выкладываются только один раз! странно!

В конце, я извиняюсь, что не могу поделиться каким-либо реальным кодом, потому что это не тестовый проект, а сложность реализаций делает бесполезным совместное использование кода, если он не понят в целом.

Спасибо за ваше время.

6 ответов

Решение

Если кто-то сталкивался с такой же проблемой:

Если вы рассчитываете высоту вашей ячейки и ее элементов, и вы зависите от NSIndexPath для запроса каких-либо данных или условий всегда проверяйте правильность пути индекса (не nil). Большинство UITableView методы, которые возвращают путь индекса (например, -(NSIndexPath *)indexPathForCell:..и т. д.) может вернуться nil значения и будет сбивать вас по спирали, которая отлаживает представления.

В моем случае у меня был метод, чтобы определить, должна ли моя ячейка иметь заголовок, и для этого я проверил, является ли это первая ячейка или условие изменилось с предыдущей ячейки. проблема была indexPath.row == 0 верно, даже если путь индекса на самом деле nil (это концептуальная проблема в Objective-C, где nil это 0). поэтому на короткое время мои клетки подумали, что у них есть заголовок!

Я чувствую себя глупо, не проверяя nil индексные пути, но я думаю, что когда-нибудь это может кому-нибудь помочь.

Я также столкнулся с той же проблемой мерцания UITableViewCell при использовании reloadRowsAtIndexPath, поэтому я сделал следующее:

     [UIView setAnimationsEnabled:NO];
     [self.tableView beginUpdates];

     [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil]
                                               withRowAnimation:UITableViewRowAnimationNone];
     [self.tableView endUpdates];
     [UIView setAnimationsEnabled:YES];

Приведенный выше фрагмент не будет содержать анимацию в ячейках при перезагрузке ячейки.

Да, вы можете добиться аналогичного результата из ответа @Sandy, используя performWithoutAnimation (Swift Version)

UIView.performWithoutAnimation {
      self.tableView.reloadRows(at: [indexPath], with: .none)
}

В быстром я использую это, и это уменьшает мерцание

let visibleIndexs = self.ContentTableview.indexPathsForVisibleRows! as NSArray
        print(visibleIndexs)
        for indx in visibleIndexs {
            if self.imgDownloadedIndexs!.containsObject(indx) {
                  UIView.setAnimationsEnabled(false)
                self.ContentTableview.beginUpdates()
                self.ContentTableview.reloadRowsAtIndexPaths([indx as! NSIndexPath], withRowAnimation:.None)
                self.ContentTableview.endUpdates()
                 UIView.setAnimationsEnabled(true)
                self.imgDownloadedIndexs?.removeObject(indx)

            }

Удаление метода rowHeightAtIndexPath решит эту проблему. убедитесь, что вы установили некоторую фиксированную высоту ячейки таблицы в раскадровке.

Пользовательская ячейка tableView не была задействована и мерцала. Это было из-за клеточной анимации. После добавления приведенного ниже кода ячейка становится доступной и работает нормально. Этот случай происходит нормально, а также может возникнуть во время выполнения UITestCase.

      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
   UIView.performWithoutAnimation {
      self.tableView.reloadRows(at: [indexPath], with: .none)
  }
return cell
}
Другие вопросы по тегам