NSFetchedResultsController плюс NSBatchUpdateRequest равно NSMergeConflict. Что я делаю не так?
Я получил NSFetchedResultsController
что я настроил с помощью NSManagedObjectContext
, Я выполняю выборку, используя этот контекст.
У меня также есть NSBatchUpdateRequest
что я настроил, используя тот же NSManagedObjectContext
, Я выполняю запрос, используя тот же NSManagedObjectContext
,
Когда я выполняю запрос с NSBatchUpdateRequest
Я вижу, что все мои данные были обновлены. Если я перезапустить приложение, любой выбор с помощью NSFetchedResultsController
тоже работает.
Проблема в том, что когда я не перезагружаю приложение и выполняю обе операции один за другим, я получаю NSMergeConflict (0x17427a900) for NSManagedObject (0x1740d8d40) with objectID '0xd000000001b40000...
ошибка при вызове метода save
из моего контекста.
Я знаю, что проблема возникает из-за одновременного изменения одних и тех же данных, но я не знаю, каково решение? Можно было бы пройти через NSMergePolicy
класс, но я сомневаюсь, что это чистый способ решить мою проблему.
Что я должен делать? Есть два разных контекста? (как?)
1 ответ
Ну, кажется, я мог бы найти, как это сделать, но если вы видите что-то не так, пожалуйста, дайте мне знать.
Когда вы выполняете пакетное обновление, у вас есть возможность получить в результате, независимо от того, что ничего - количество обновленных строк или список идентификаторов объектов, которые были обновлены. Вы должны выбрать последний.
После того, как вы выполните executeRequest
из контекста, вам нужно получить список идентификаторов объектов, перебрать все из них, чтобы получить каждый NSManagedObject
в неисправности благодаря методу objectWithID
объекта контекста. Если вы не знаете, что такое объект Faults в Базовых данных, вот объяснение.
С каждым NSManagedObject
вы получаете, вам нужно обновить контекст, используя его метод refreshObject
,
После того, как вы это сделали, вам нужно снова выполнить performFetch
вашей fetchedResultsController
чтобы вернуться туда, где вы были до пакетного обновления.
Скажи мне, если я где-то не прав.
Вот код:
let batchUpdate = NSBatchUpdateRequest(entityName: "myEntity")
batchUpdate.propertiesToUpdate = ["myPropertieToUpdate" : currency.amountToCompute]
batchUpdate.affectedStores = managedContext.persistentStoreCoordinator?.persistentStores
batchUpdate.resultType = .UpdatedObjectIDsResultType
var batchError: NSError?
let batchResult = managedContext.executeRequest(batchUpdate, error: &batchError) as NSBatchUpdateResult?
if let result = batchResult {
println("Records updated \((result.result as [NSManagedObjectID]).count)")
// Extract Object IDs
let objectIDs = result.result as [NSManagedObjectID]
for objectID in objectIDs {
// Turn Managed Objects into Faults
let nsManagedObject: NSManagedObject = managedContext.objectWithID(objectID)
if let managedObject = nsManagedObject as NSManagedObject? {
managedContext.refreshObject(managedObject, mergeChanges: false)
}
}
// Perform Fetch
var error: NSError? = nil
if !fetchedResultsController.performFetch(&error) {
println("error: + \(error?.localizedDescription), \(error!.userInfo)")
}
} else {
println("Could not update \(batchError), \(batchError!.userInfo)")
}
РЕДАКТИРОВАТЬ: Вот две ссылки для большего количества объяснений:
http://code.tutsplus.com/tutorials/ios-8-core-data-and-batch-updates--cms-22164
http://www.bignerdranch.com/blog/new-in-core-data-and-ios-8-batch-updating/