UITableView endUpdates занимает очень много времени, когда обновления CoreData

У меня есть приложение Core Data, которое отображает большое количество экземпляров в UITableView .

У нас есть mainQueueContext работающий в основном потоке, и privateQueueContext работающий в фоновом потоке.

Мы загружаем данные в UITableView без проблем, но когда мы загружаем обновленную версию из API, мы сохраняем ее в privateQueueContext и объединяем ее в mainQueueContext

 [self.mainQueueContext mergeChangesFromContextDidSaveNotification:notification]; 

Для вызова вызова требуется несколько секунд.

 -(void)controllerDidChangeContent:(NSFetchedResultsController *)controller 

Который вызывает вызов:

 [self.tableView endUpdates]; 

Затем приложение зависает, а процессор переходит на 100%, и память начинает расти бесконечно, пока не закончится память. (см. рисунок ниже)

Процессор во время обработки

Потребление памяти во время endUpdates

С менее чем 1000 элементов эта проблема не возникает. Мне было интересно, видел ли кто-нибудь что-то подобное.

редактировать

Вот некоторые данные из инструментов Данные инструментов, показывающие endUpdates

3 Solutions collect form web for “UITableView endUpdates занимает очень много времени, когда обновления CoreData”

Одно из улучшений, которое вы можете сделать, это использовать fetchBatchSize .

От Apple Doc "

Когда выполняется выборка, оценивается весь запрос и записываются идентификаторы всех совпадающих объектов, но не более, чем данные объектов batchSize будут извлекаться из постоянного хранилища за раз. Массив, возвращенный из выполнения запроса, будет прокси-объектом, который прозрачно разбивает пакеты по требованию. (В терминах базы данных это курсор в памяти).

Вы также можете использовать fetchLimit и fetchOffset для реализации разбивки на страницы.

Приветствия, Алессандро

Я тоже испытал эту проблему. Я закончил собирать все обновленные в массив на controller: didChangeObject: запись указательного пути, NSFetchedResultsChangeType и сам объект. В controllerDidChangeContent: я смотрел, если его счет больше X, если он просто перезагружает всю таблицу (это намного эффективнее), и если это не так, то все изменения обычно применяются так же, как если бы это происходило в didChangeObject: Просто не имеет смысла вставлять / удалять / перемещать так много ячеек, так как пользователь все равно не увидит большинство этих изменений.

Надеюсь, этот подход поможет вам!

Я столкнулся с подобной проблемой. В моем случае решение заключалось в том, чтобы удалить установку явно rowHeight таблицыView в UITableViewAutomaticDimension :

 tableView.rowHeight = UITableViewAutomaticDimension 

Вместо этого я использовал делегат tableView(_:heightForRowAt:) Хотя в документации rowHeight, похоже, указано противоположное:

Есть последствия для использования tableView ( : heightForRowAt 🙂 вместо rowHeight. Каждый раз, когда отображается табличное представление, он вызывает tableView ( : heightForRowAt 🙂 для делегата для каждой из его строк, что может привести к значительной проблеме с представлением таблицы с большим количеством строк (приблизительно 1000 или более).

  • Как сделать копию объекта Core Data, которая остается нетронутой
  • Получение NSFetchedResultsController, NSSortDescription и sectionNameForKeyPath для совместной работы
  • cellForRowAtIndexPath не вызывается после reloadRowsAtIndexPaths
  • CoreData обнаруживает удаленный объект после сохранения
  • UIManagedDocument с NSFetchedResultsController и фоновым контекстом
  • Показывать ярлык, если вид таблицы пуст
  • Свойство не найдено на объекте ... свойств отладки ошибок в NSManagedObjects
  • Предельные результаты NSPredicate
  • malloc: *** ошибка для объекта 0x14d3e300: double free CoreData
  • Пользовательский init для подкласса NSManagedObject
  • Необходимо уточнить код ошибки Cocoa 1570
  • PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.