Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data NSFetchedResultsController not updated after a batchUpadate on the device but ok on simulator

I have a NSFetchedResultsController that managed my UITableView data source.

I am trying to modify a property of a NSManagedObject called amountToCompute using a NSBatchUpdateRequest. So I create the batch update:

let batchUpdate = NSBatchUpdateRequest(entityName: "MyEntity")
batchUpdate.propertiesToUpdate = ["amountToCompute" : newAmount]
batchUpdate.resultType = .UpdatedObjectIDsResultType

I execute it:

var batchError: NSError?
let batchResult = managedContext.executeRequest(batchUpdate, error: &batchError) as! NSBatchUpdateResult?

And to update my current managed context, I update each managedObject in the managedContext and perform a new fetch of fetchedResultsController:

if let result = batchResult {
    let objectIDs = result.result as! [NSManagedObjectID]

    for objectID in objectIDs {
        let managedObject: NSManagedObject = managedContext.objectWithID(objectID)

        if !managedObject.fault {
            managedContext.refreshObject(managedObject, mergeChanges: true) 
        }

        if !fetchedResultsController.performFetch(&error) {
            println("error: + \(error?.localizedDescription), \(error!.userInfo)")
        }
    }
}

I implemented some methods of the delegate NSFetchedResultsControllerDelegate to manage changes in the results sent by the NSFetchedResultsController:

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    tableView.beginUpdates()
}

    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {

        switch type {
        ... 
        case .Update:
            reloadRowsAtIndexPaths([indexPath!], animation: reloadRowsWithAnimation)
            let myManagedObject = anObject as! MyManagedObject
            println("update : \(myManagedObject.amountToCompute)")
        ...
        }
    }

    func controllerDidChangeContent(controller: NSFetchedResultsController) {
        tableView.endUpdates()
    }

I run the app on my 8.4 iOS simulator and everything goes fine. println("update : \(myManagedObject.amountToCompute)") prints the new value.

I run the app on my iPhone 6 8.4.1 and the value is not updated, println("update : \(myManagedObject.amountToCompute)") prints the old value. The new value is saved properly but the changes don't appear in my table view while they do on the simulator.

What's wrong? How come it can be different whether I'm on the simulator or on my device. The versions are not exactly the same but I doubt Apple touched Core Data architecture in their last update.

like image 682
Nico Avatar asked Aug 25 '15 05:08

Nico


1 Answers

This is a an unusual, but known problem that I ran into myself and spent a couple of days pulling out my hair until found this blog post, which worked for me.

https://stevenpsmith.wordpress.com/2011/08/12/nsfetchedresultscontroller-and-core-data-managed-object-updates/

It boiled down to adding this single line of code that set the staleness interval to zero:

[context setStalenessInterval:0];

If I'm reading your post right you're having the same issue. :)

like image 179
J-Boss Avatar answered Nov 09 '22 20:11

J-Boss