У меня есть NSOperation
, который обновляет данные приложений. Эта операция имеет свой собственный контекст, и изменения передаются обратно в контекст основного потока через уведомление contextDidSave
.
Операция обновления удаляет объекты. Эти удаления непреднамеренно вызывают сбой. Сбой происходит, когда основной поток перезагружает UITableView
одновременно с сохранением контекста обновления. Источник данных для табличного представления поддерживается NSFetchedResultsController
.
Ни CoreData, ни UIKit не выводят никаких записей. Сбой SIG_ABRT возникает в tableView:cellForRowAtIndexPath:
при доступе к атрибуту managedObject. Вот результат успешного обновления. Вы можете видеть, что таблица заполняется один раз, затем контекст сохраняется, что, в свою очередь, приводит к перезагрузке таблицы:
tableView:numberOfRowsInSection: rowCount = 29
tableView:cellForRowAtIndexPath: row: 0
tableView:cellForRowAtIndexPath: row: 1
tableView:cellForRowAtIndexPath: row: 2
tableView:cellForRowAtIndexPath: row: 3
tableView:cellForRowAtIndexPath: row: 4
tableView:cellForRowAtIndexPath: row: 5
tableView:cellForRowAtIndexPath: row: 6
tableView:cellForRowAtIndexPath: row: 7
tableView:cellForRowAtIndexPath: row: 8
tableView:cellForRowAtIndexPath: row: 9
Will saved update context
Did saved update context
Will merge update context
tableView:numberOfRowsInSection: rowCount = 58
Did merge update context
tableView:numberOfRowsInSection: rowCount = 29
tableView:cellForRowAtIndexPath: row: 0
tableView:cellForRowAtIndexPath: row: 1
tableView:cellForRowAtIndexPath: row: 2
tableView:cellForRowAtIndexPath: row: 3
tableView:cellForRowAtIndexPath: row: 4
tableView:cellForRowAtIndexPath: row: 5
tableView:cellForRowAtIndexPath: row: 6
tableView:cellForRowAtIndexPath: row: 7
tableView:cellForRowAtIndexPath: row: 8
tableView:cellForRowAtIndexPath: row: 9
А вот вывод, когда произошел сбой:
tableView:numberOfRowsInSection: rowCount = 29
tableView:cellForRowAtIndexPath: row: 0
tableView:cellForRowAtIndexPath: row: 1
tableView:cellForRowAtIndexPath: row: 2
Will saved update context
tableView:cellForRowAtIndexPath: row: 3
tableView:cellForRowAtIndexPath: row: 4
tableView:cellForRowAtIndexPath: row: 5
![stacktrace](https://i.stack.imgur.com/hsRfB.png)
Я могу придумать два возможных решения:
- заблокировать
persitentStoreCoordinator
, пока обновляется табличное представление. (Это может быть сделано путем создания подкласса UITableView
и переопределения reloadData
для предоставления места для блокировки и разблокировки магазина)
- Отложить удаление до более поздней даты, например, когда приложение закрывается. (Это можно сделать, добавив атрибут
isStale
к сущностям или создав новую сущность Trash
и добавив к ней объекты.)
Тем не менее, оба эти решения кажутся действительно хакерскими. Я что-то пропустил? Сначала я попытался сделать предварительный выбор NSFetchedResultsController
всех объектов, но это невозможно. Другим возможным решением было заблокировать хранилище при использовании controllerDidChangeContent:
, но проблема все еще возникает, когда перезагрузка таблицы не запускается fetchedResultsController.