I can't handle this problem, I'm trying to integrate iCloud and Core Data to my app and I stuck with iCloud synchronization part.
My complete scenario:
If we take away discussion about migration and focus on loading persistent store coordinator with iCloud, I think that the problem is related toNSPersistentStoreCoordinatorStoresDidChangeNotification
event.
I just don't understand it. In every article that I read, I saw something like: "reload you UI here". But it doesn't work for me.
Reload coordinator function
func configureContext() -> NSManagedObjectContext? {
// Create the coordinator and context
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
//remove all observers from "previous" coordinator
deregisterForStoreChanges()
//and register them for new one
registerObservers(persistentStoreCoordinator: coordinator)
do {
//storeSettings.url = applicationDocumentsDirectory.URLByAppendingPathComponent("iCloud.sqlite")
//storeSettings.options = [NSPersistentStoreUbiquitousContentNameKey:"iCloudProject"]
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeSettings.url, options: storeSettings.options)
} catch {
//Here was standard error handler I didn't changed it, but removed for listing
abort()
}
persistentStoreCoordinator = coordinator
let managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = coordinator
//not quite sure about the next string, didn't test it yet
managedObjectContext.mergePolicy = NSMergePolicy(mergeType:NSMergePolicyType.MergeByPropertyStoreTrumpMergePolicyType )
//tried to refetch my records here but, with no luck.
//refetchUIRecords()
return managedObjectContext
}
And my NSPersistentStoreCoordinatorStoresDidChangeNotification
event func
func persistentStoreCoordinatorDidChangeStores(notification:NSNotification){
if notification.userInfo?[NSAddedPersistentStoresKey] != nil {
print("-----------------------")
print("ADDED")
print("-----------------------")
//deduplicateRecords()
//if iCloud -> refetch UI
if NSUserDefaults.standardUserDefaults().boolForKey("iCloud"){
self.createTimer()
}
}
print("Did Change")
}
Create timer function is just a function which wait for 1 secods before actual refetching and refreshing UI.
The problem
When we reach step 4 from my scenario, and call configureContext function, I see this in the console:
2016-04-12 13:31:27.749 TestingiCloudProject[2052:1142902] -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](898): CoreData: Ubiquity: mobile~567404C0-9D84-4C07-A0F8-D25832CB65D8:iCloudProject
Using local storage: 1 for new NSFileManager current token <ef7a917f bca47ecf 5d58862d cbe9998d 7e53e5ea>
Did Change
Did Change
-----------------------
ADDED
-----------------------
Timer
Did Change
Refetch
Refetching...
Number of records after fetch: 1 //must be more than 1
2016-04-12 13:31:30.090 TestingiCloudProject[2052:1143055] -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](898): CoreData: Ubiquity: mobile~567404C0-9D84-4C07-A0F8-D25832CB65D8:iCloudProject
Using local storage: 0 for new NSFileManager current token <ef7a917f bca47ecf 5d58862d cbe9998d 7e53e5ea>
As you can see my fetch request executes before Using local storage: 0
and that's why I'm recieving records from the local storage (1 record) not iCloud (which contains more than 1).
I don't understand when to refetch my records. I take timer part from this great source for all who want to know more about Core Data and iCloud. But, 1 second isn't enought, 2 seconds is work as I want, but what if iCloud store will be bigger than mine, or network connection will be worse than mine, I don't think that timer is the way.
I hope somebody already face this trivial problem.
EDIT
I didn't find any help from Apple dev forum and SO, so I activated my code tech support token, I hope they can help me. As soon as I'll solve my problem I'll write an answer. But, if you, who read this question, know the possible answer, post it now.
There is another notification NSPersistentStoreDidImportUbiquitousContentChangesNotification
that is fired by the persistent store coordinator whenever data is imported from the ubiquitous content store. Here you can merge the changes with your NSManagedObjectContext.
When the ubiquity container receives changes from iCloud, Core Data posts an NSPersistentStoreDidImportUbiquitousContentChangesNotification notification. This notification’s userInfo dictionary is structured similarly to that of an NSManagedObjectContextDidSaveNotification notification except for that it contains NSManagedObjectID instances rather than NSManagedObject instances. Therefore you can merge in changes from other peers in the same way that you merge changes from other managed object contexts. Call mergeChangesFromContextDidSaveNotification: on your managed object context, passing in the notification object posted by Core Data.
https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/UsingCoreDataWithiCloudPG/UsingSQLiteStoragewithiCloud/UsingSQLiteStoragewithiCloud.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With