-1

i have an app in which i sync my Core Data via iCloud. The sync is working properly, but the tableView in which i'm displaying the data (in a view called 'ResultsView') won't reload after the iCloud sync; i need to go to another view and go back to my ResultsView to see the changes.

This is how i handle the sync of my Core Data (in AppDelegate.swift):

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
    // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
    // Create the coordinator and store
    var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("MyApp.sqlite")
    var error: NSError? = nil
    var failureReason = "There was an error creating or loading the application's saved data."
    // iCloud store
    var storeOptions = [NSPersistentStoreUbiquitousContentNameKey : "MyAppStore",NSMigratePersistentStoresAutomaticallyOption: true,
        NSInferMappingModelAutomaticallyOption: true]
    // iCloud storeOptions need to be added to the if statement
    do {
        try coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: NSURL.fileURLWithPath(url.path!), options: storeOptions)
    } catch var error1 as NSError {
        error = error1
        coordinator = nil
        // Report any error we got.
        var dict = [String: AnyObject]()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
        dict[NSLocalizedFailureReasonErrorKey] = failureReason
        dict[NSUnderlyingErrorKey] = error
        error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
        // Replace this with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog("Unresolved error \(error), \(error!.userInfo)")
        abort()
    } catch {
        fatalError()
    }

    return coordinator
}()

Also in AppDelegate, to handle the updates via iCloud:

// MARK: - iCloud
// This handles the updates to the data via iCLoud updates

func registerCoordinatorForStoreNotifications (coordinator : NSPersistentStoreCoordinator) {
    let nc : NSNotificationCenter = NSNotificationCenter.defaultCenter();

    nc.addObserver(self, selector: "handleStoresWillChange:",
        name: NSPersistentStoreCoordinatorStoresWillChangeNotification,
        object: coordinator)

    nc.addObserver(self, selector: "handleStoresDidChange:",
        name: NSPersistentStoreCoordinatorStoresDidChangeNotification,
        object: coordinator)

    nc.addObserver(self, selector: "handleStoresWillRemove:",
        name: NSPersistentStoreCoordinatorWillRemoveStoreNotification,
        object: coordinator)

    nc.addObserver(self, selector: "handleStoreChangedUbiquitousContent:",
        name: NSPersistentStoreDidImportUbiquitousContentChangesNotification,
        object: coordinator)
}

I have the fetch of my Core Data in the viewWillAppear method of my ResultsView, as well as self.tableView.reloadData() in both viewWillAppear and viewDidAppear.

What am i missing?

Thanks in advance

CarlosBF
  • 144
  • 11

1 Answers1

0

[Edit - didn't read question properly!]

If your data can change whilst the view is open (which is likely as iCloud syncing is asynchronous): your view needs to know that the data it is based on has changed, so after your CoreData is synchronised call setNeedsDisplay on it. See also this SO answer.

If your data cannot change whilst the view is open, in viewWillAppear ensure that the data is synchronised completely before you call super. Note that syncing with iCloud will be asynchronous, so just calling the sync method will not be sufficient. It is possibly just easier to assume that it will change whilst the view is open as described above.

Community
  • 1
  • 1
Ali Beadle
  • 4,202
  • 3
  • 26
  • 53
  • Thanks for answering. Sorry for asking again, but where should i call `setNeedsDisplay`? I've tried both in `viewDidLoad` and in a function tracking `NSPersistentStoreDidImportUbiquitousContentChangesNotification` but doesn't work. I need to go to another view and enter in my view again to see the changes. Thanks again – CarlosBF Jan 17 '16 at 15:16
  • @CarlosBF You should not need it in viewDidLoad - the system will draw the view when it first appears. I am not sure if I can help further on exactly when to trigger setNeedsDisplay - CoreData is great for local data but notoriously complex for iCloud syncing, so I switched to CloudKit for that after a lot of frustration. It may be worth a separate question to get a 'CoreData with iCloud' expert to tell you from which notification to trigger your view to redraw. – Ali Beadle Jan 17 '16 at 15:53