简体   繁体   中英

How do I store core data logs when iCloud isn't enabled?

I want the user to be able to keep on using the core data store as normal when iCloud is disabled. The only problem I'm having with that is that they might have a lot of data which produced logs when it was enabled, and then if they enable it again, i'm stuck with either not adding all the data they made since then or adding all data, thus duplicating the existing data. To avoid this problem, I want to keep making logs when iCloud is disabled, so it can just upload those changes when it is enabled again.

This is the code I have to do it when connected to iCloud:

NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];

NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];

NSMutableDictionary *options = [NSMutableDictionary dictionary];
        [options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
        [options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
        [options setObject:iCloudEnabledAppID            forKey:NSPersistentStoreUbiquitousContentNameKey];
        [options setObject:iCloudLogsPath                forKey:NSPersistentStoreUbiquitousContentURLKey];

[psc addPersistentStoreWithType:NSSQLiteStoreType
                          configuration:nil
                                    URL:store
                                options:options
                                  error:nil];

Unfortunately this is not an option. When iCloud is enabled and you use NSPersistentStoreUbiquitousContentNameKey , Core Data transaction logs are created automatically. In every other case, no transaction logs get created. There is no way for your code to force the logs to be created without having iCloud enabled. This kind of situation is just one of many unexpected complications when attempting to use iCloud with Core Data.

One possible approach: When you discover that iCloud has been enabled, migrate your entire data store to iCloud and don't worry about whether anything is already there. Then, use a duplicate detection method to weed out duplicate entries. Apple provided a good example of duplicate detection code in their SharedCoreData sample project, covered at WWDC 2012 session 227, Using iCloud with Core Data .

Another approach would be to maintain your own change logs while iCloud is disabled. Use NSManagedObjectContextDidSaveNotification to watch for changes, and keep your own list of objects that changed while iCloud was disabled. If iCloud is reenabled, you can then re-save those objects to generate iCloud transactions for them.

With either of those, though, there are a couple of related complications to consider:

  1. If the user disables iCloud while your app is running, you cannot continue using your existing persistent store coordinator or even your existing data store. If you do, your app will attempt to write transaction logs, fail because there's no place to put them, and then crash. You'll need to move to a new, non-iCloud data store. You can probably use migratePersistentStore:toURL:options:withType:error: to do this in one step, but you must do it. (As an aside, it might be possible to just mess with the data store's metadata, but this is undocumented and I don't know what key(s) to wipe out).

  2. Related to the above, if the user reenables iCloud, you'll need to migrate back to an iCloud-enabled data store.

  3. If iCloud is not enabled when your app starts up, you should really just use nil for the options when setting up the persistent store coordinator. Check the value returned by URLForUbiquityContainerIdentifier: and proceed with or without iCloud accordingly.

  4. In my experience-- Core Data with iCloud is flaky . Among other things, be certain to check the return value from addPersistentStoreWithType:etc because it might fail for no readily apparently reason (ie you did everything right but iCloud is just not behaving).

Good luck, you will need it. Keep in mind that as of today, even Apple doens't use iCloud with Core Data in any of their own apps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM