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/

Другие вопросы по тегам