insertRowsAtIndexPaths, вызывающий cellForRowAtIndexPath для каждой строки - PullRequest
3 голосов
/ 21 мая 2011

Я пытаюсь вставить несколько строк в пустой UITableView за один шаг, используя insertRowsAtIndexPaths. (Я знаю, что это звучит не так уж и полезно, но это упрощенная версия того, что мне действительно нужно делать.)

Проблема, с которой я сталкиваюсь, заключается в том, что после выполнения вызова insertRowsAtIndexPaths я получаю вызовы cellForRowAtIndexPath для каждой вставленной строки, а не только для видимых.

Это не похоже на правду. И для меня это почти бесполезно, если он делает это.

Единственный немного странный другой артефакт, который я вижу, заключается в том, что когда я делаю это, он на самом деле, кажется, оживляет ряды на месте. Это не withRowAnimation, так как для него установлено значение none. Но, похоже, здесь происходит какая-то концепция анимации более высокого уровня. У меня была идея, что, когда он анимировал ряды на месте, он подумал, что ему нужны ячейки для большего количества / всех рядов, пока они не будут вытеснены с экрана. Но я не могу отключить эту анимацию без использования reloadData, которого я бы предпочел избежать.

Обычно у меня есть набор данных, который меняется за кулисами. Я могу тщательно пройтись и сконструировать изменения, чтобы сгенерировать данные для вызовов вставки / удаления / перезагрузки. Но я не могу ограничить это тем, что отображается на экране, поскольку оно не соответствует поставщику данных.

Я полагаю, я что-то упускаю ... есть идеи?

(Я делаю это в паре beginUpdates / endUpdates, но, похоже, это не имеет значения.)

Ответы [ 8 ]

5 голосов
/ 10 июня 2011

Я разговаривал с некоторыми людьми из Apple сегодня. Эта проблема определенно связана с анимацией, которую выполняет UITableView при вставке новых строк. Это анимация, которая создается для создания новых строк для ячеек, отдельно от анимации, которая используется, когда эти строки вводятся через insertRowsAtIndexPaths.

Поскольку анимация на уровне таблицы создает новые строки с помощью некоего «растущего» вида, во время анимации вставки небольшое количество многих ячеек считается видимым, и таблица будет вызывать для них cellForRowAtIndexPath.

Кажется, для этого нет альтернативной реализации, которая бы работала во всех случаях. Рекомендованное решение для моего случая - «лежать»: выяснить, какие ячейки будут существовать на странице после анимации, и вставить их. После завершения анимации вставьте оставшиеся ячейки, которые не будут отображаться, и таблица не будет вызывать cellForRowAtIndexPath.

Это требует реализации объекта между табличным представлением и «реальным» источником данных, который может «лежать» в табличном представлении о количестве строк в таблице на протяжении анимации. Больно, но это, очевидно, то, что было сделано в подобных случаях.

2 голосов
/ 11 сентября 2012

Мне удалось решить эту проблему, соединив несколько ответов отсюда:

установить булево значение для массивной нагрузки, как это требуется в соответствии с pocjoc

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
    UITableView *tableView = self.tableView;
    switch(type) {
        case NSFetchedResultsChangeInsert:
            massiveLoad = YES;
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        ...
    }
}

и перезагрузите видимые строки, когда он заканчивается

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
    if (massiveLoad) {
        massiveLoad = NO;
        [self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationFade];
    }
}
2 голосов
/ 26 января 2012

У меня была та же проблема, что я сделал, объявив атрибут bMassiveLoad, инициализированный как false.Перед тем, как выполнить «массивную загрузку», я установил для нее значение true, и первое, что я сделал в cellForRowAtIndexPath, - это проверил этот атрибут.В конце «maseive load» я снова установил значение «false» и вызвал reloadData ...

Я знаю, что это не красивый ответ, но он мне помогает.

0 голосов
/ 12 ноября 2016

Для быстрого вы можете попробовать это

self.mainTableView.beginUpdates()
    self.mainTableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: UITableViewRowAnimation.Fade)
    self.mainTableView.reloadRowsAtIndexPaths(self.mainTableView.indexPathsForVisibleRows!, withRowAnimation: UITableViewRowAnimation.Fade)
    self.mainTableView.endUpdates()
0 голосов
/ 21 мая 2011

UITableView будет запрашивать видимые ячейки методом cellForRowAtIndexPath:, и это может сократить время обработки, когда имеется много ячеек, например, 1к ячейки, и уменьшить затраченную память с помощью механизма многоразовых ячеек. Если вам нужно обработать все ячейки, вам следует реализовать собственный метод для повторной обработки исходных данных, а затем вызвать [tableView reloadData] для обновления пользовательского интерфейса.

0 голосов
/ 21 мая 2011

Я не знаю, правильно ли описанное вами поведение, но у UITableView есть два метода: beginUpdates и endUpdates ( здесь ), предназначенные для оптимизации перерисовки (чтобыанимация выполняется только в конце, в противном случае они выполняются один за другим, и это может вызвать вызов cellForRowAtIndexPath).

Теперь я не уверен, может ли это помочь вам, но, возможно, вы можетепопробуй ...

0 голосов
/ 21 мая 2011

Я чувствую, что может быть другой способ сделать это, но я обнаружил, что если у вас есть существующие ячейки в видимом диапазоне (например, если у вас есть 10 ячеек, видимых постоянно, и вы инициализируетеtableView с 10 пустыми ячейками), когда вы добавляете новые строки, дополнительные строки не вызываются в cellForRowAtIndexPath.

Итак, что с этим делать.Вот так я и исправил это.Когда я создал tableView, я добавил ячейки в видимую область.Они были пустыми.Затем, когда я вставил новые строки, я добавил только пути индекса для дополнительных строк (т.е. если у меня есть 10 видимых строк и я хочу добавить 50 строк, включая видимые строки, я добавил только 40, поскольку первые 10 уже существуют).Это, конечно, оставляет вам 10 пустых клеток.На этом этапе вы можете использовать:

NSArray *indexPaths = [myTableView indexPathsForVisibleCells];
[myTableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];

. Он выбирает ваши 10 видимых пустых ячеек и загружает их с новой информацией, которую вы передали (я предполагаю, что вы загружаете данные в массив для этой части).Вам нужно будет добавить немного логики к вашему cellForRowAtIndexPath методу, например:

if (![myDataArray count]) {
    // create a blank cell;
} else {
    // add context to your cells as you want;
}

Это должно помочь вам и загрузить только те ячейки, которые вы видите на экране

0 голосов
/ 21 мая 2011

UITableView вызывает соответствующие методы делегата и источника данных сразу после вызова insertRowsAtIndexPaths, чтобы получить ячейки и другое содержимое для видимых ячеек. Это независимо от того, установлено или нет анимированное значение ДА или НЕТ.

Смотрите обсуждение здесь

Если вы хотите, чтобы tableView обновлял видимые ячейки, просто обновите ваш источник данных и вызовите [tableView reloadData].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...