The iPhone/iOS app is using CoreData + SQLite (NSSQLiteStoreType) + iCloud iOS. When the app starts on first install (or after deleting and reinstalling via xcode), and there is prior app data in iCloud from a prior installation or from other devices in the same account, the following error occurs, then a 60 second retry delay, then a successful migration to iCloud. The result is that user of the app thinks that their data is lost when the app is upgraded. However, after the 60 second delay, the data is restored. The error and some code follows.
What causes this error? Where can I learn more about this error?
[4972:2014294] CoreData: iCloud: Error: initial sync notification returned an error (Error Domain=BRCloudDocsErrorDomain Code=12 "The operation couldn't be completed. (BRCloudDocsErrorDomain error 12.)")
[4972:2014294] -PFUbiquitySetupAssistant finishSetupWithRetry:: CoreData: Ubiquity: : Retrying after delay: 60 Error Domain=BRCloudDocsErrorDomain Code=12 "The operation couldn't be completed. (BRCloudDocsErrorDomain error 12.)"
Here is a code snippet and more detailed log to provide more context.
From the app delegate:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
... standard iCloud and app setup ...
NSManagedObjectContext *context = [self managedObjectContext];
...
... query the db ...
}
/**
Returns the managed object context for the application.
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
*/
- (NSManagedObjectContext *) managedObjectContext {
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
}
managedObjectContext.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
return managedObjectContext;
}
...
/**
Returns the managed object model for the application.
If the model doesn't already exist, it is created by merging all of the models found in the application bundle.
*/
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return managedObjectModel;
}
...
/**
Returns the persistent store coordinator for the application.
If the coordinator doesn't already exist, it is created and the application's store added to it.
*/
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES) lastObject] stringByAppendingPathComponent: @"myapp.sqlite"]];
NSLog(@"App Store URL : %@", storeUrl);
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSDictionary *storeOptions;
storeOptions = @{
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
NSPersistentStoreUbiquitousContentNameKey: @"AppCloudStore"
};
#ifdef FREE
storeOptions = @{
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES,
NSPersistentStoreUbiquitousContentNameKey: @"FreeAppCloudStore"
};
#endif
// Register for Notifications
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter addObserver:self
selector:@selector(storesDidChange:)
name:NSPersistentStoreCoordinatorStoresDidChangeNotification
object:self.persistentStoreCoordinator];
[notificationCenter addObserver:self
selector:@selector(persistentStoreDidImportUbiquitousContentChanges:)
name:NSPersistentStoreDidImportUbiquitousContentChangesNotification
object:self.persistentStoreCoordinator];
[notificationCenter addObserverForName:NSPersistentStoreCoordinatorStoresWillChangeNotification
object:self.persistentStoreCoordinator
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note) {
NSLog(@"Stores Will Change...");
if ([self.managedObjectContext hasChanges]) {
NSError *saveError;
if (![self.managedObjectContext save:&saveError]) {
NSLog(@"Save error: %@", saveError);
}
} else {
// drop any managed object references
[self.managedObjectContext reset];
}
}];
NSPersistentStore *store = [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:storeOptions error:&error];
if (store == nil || error != nil) {
NSLog(@"Error: %@, %@", error, [error userInfo]);
abort();
}
NSURL *finaliCloudURL = [store URL];
NSLog(@"Created persistent store okay. Final iCloud URL is: %@", finaliCloudURL);
return persistentStoreCoordinator;
}
...
- (void)persistentStoreDidImportUbiquitousContentChanges:(NSNotification *)notification {
NSLog(@"persistentStoreDidImportUbiquitousContentChanges: Called. Content has changed via Core Data iCloud: *******************************************");
// Received and merge updates from iCloud
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
[self notifyAndRefreshAllDataDueToCloudEvent];
}
...
- (void)storesDidChange:(NSNotification *)notification {
// Tell me: why did my stores changes?
NSNumber *transitionType = [notification.userInfo objectForKey:NSPersistentStoreUbiquitousTransitionTypeKey];
int theCause = [transitionType intValue];
NSLog(@"storesDidChange: NSPersistentStoreCoordinatorStoresDidChange Notification = %@", notification);
switch (theCause) {
case NSPersistentStoreUbiquitousTransitionTypeAccountAdded: {
NSLog(@"storesDidChange: Account Added");
// account was added
}
break;
case NSPersistentStoreUbiquitousTransitionTypeAccountRemoved: {
NSLog(@"storesDidChange: Account Removed");
// account was removed
}
break;
case NSPersistentStoreUbiquitousTransitionTypeContentRemoved: {
NSLog(@"storesDidChange: Content Removed");
// content was removed
}
break;
case NSPersistentStoreUbiquitousTransitionTypeInitialImportCompleted: {
NSLog(@"storesDidChange: Initial Import:");
// initial import
}
break;
default:
break;
}
...
[[NSNotificationCenter defaultCenter]
postNotificationName:@"*****DidChangeByPersistentStoreChangesNotification"
object:self];
[[NSNotificationCenter defaultCenter]
postNotificationName:@"*****DidChangeByPersistentStoreChangesNotification"
object:self];
[[NSNotificationCenter defaultCenter]
postNotificationName:@"*****DidChangeByPersistentStoreChangesNotification"
object:self];
}
More Detailed Log:
2015-05-12 10:22:23.367 [4972:2014228] storesDidChange: NSPersistentStoreCoordinatorStoresDidChange Notification = NSConcreteNotification 0x17005f470 {name = NSPersistentStoreCoordinatorStoresDidChangeNotification; object = <NSPersistentStoreCoordinator: 0x170072100>; userInfo = {
added = (
"<NSSQLCore: 0x12dd100b0> (URL: file:///var/mobile/Containers/Data/Application/****/Documents/CoreDataUbiquitySupport/mobile~****-7B78C4F2FDB2/FreeAppCloudStore/2***/store/app.sqlite)"
);
}}
2015-05-12 10:22:23.409 [4972:2014228] -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](808): CoreData: Ubiquity: mobile~****:FreeAppCloudStore
Using local storage: 1
2015-05-12 10:22:23.410 [4972:2014228] Created persistent store okay. Final iCloud URL is: file:///var/mobile/Containers/Data/Application/****/store/app.sqlite
2015-05-12 10:22:23.477 [4972:2014228] AppTableViewController:viewWillAppear: enter
2015-05-12 10:22:23.478 [4972:2014228] getSharedAdBannerView: enter
2015-05-12 10:22:23.518 [4972:2014228] queryDidUpdate: MSMetadataQuery Notification: - NSMetadataQueryDidFinishGatheringNotification
2015-05-12 10:22:23.519 [4972:2014228] queryDidUpdate: NSMetadataQuery returned 25 results
2015-05-12 10:22:23.524 [4972:2014228] setProcessTimer: 15.000000
2015-05-12 10:22:23.531 [4972:2014228] TableViewController:viewDidAppear: enter
2015-05-12 10:22:23.531 [4972:2014228] TableViewController:loadData (or reload): enter
2015-05-12 10:22:23.582 [4972:2014294] CoreData: iCloud: Error: initial sync notification returned an error (Error Domain=BRCloudDocsErrorDomain Code=12 "The operation couldn't be completed. (BRCloudDocsErrorDomain error 12.)")
2015-05-12 10:22:23.594 [4972:2014294] -[PFUbiquitySetupAssistant finishSetupWithRetry:](826): CoreData: Ubiquity: <PFUbiquitySetupAssistant: 0x12de18940>: Retrying after delay: 60
Error Domain=BRCloudDocsErrorDomain Code=12 "The operation couldn't be completed. (BRCloudDocsErrorDomain error 12.)"
2015-05-12 10:22:23.854 [4972:2014228] didFailToReceiveAdWithError
2015-05-12 10:22:55.150 [4972:2014228] bannerViewDidLoadAd
2015-05-12 10:23:24.178 [4972:2014228] queryDidUpdate: MSMetadataQuery Notification: - NSMetadataQueryDidUpdateNotification
2015-05-12 10:23:24.178 [4972:2014228] queryDidUpdate: NSMetadataQuery returned 25 results
2015-05-12 10:23:25.039 [4972:2014228] Stores Will Change...
2015-05-12 10:23:25.101 [4972:2014228] storesDidChange: NSPersistentStoreCoordinatorStoresDidChange Notification = NSConcreteNotification 0x170254940 {name = NSPersistentStoreCoordinatorStoresDidChangeNotification; object = <NSPersistentStoreCoordinator: 0x170072100>; userInfo = {
NSPersistentStoreUbiquitousTransitionTypeKey = 4;
added = (
"<NSSQLCore: 0x12dd100b0> (URL: file:///var/mobile/Containers/Data/Application/****/FreeAppCloudStore/20EF5D1C-4748-4AB2-BCE1-91B228437D77/store/app.sqlite)"
);
removed = (
"<NSSQLCore: 0x12dd100b0> (URL: file:///var/mobile/Containers/Data/Application/*****/store/app.sqlite)"
);
}}
2015-05-12 10:23:25.101 [4972:2014646] -[PFUbiquitySwitchboardEntryMetadata setUseLocalStorage:](808): CoreData: Ubiquity: mobile~*****FreeAppCloudStore
Using local storage: 0