I have a very difficult problem. I have a scenario like this:
My application uses CoreData to store objects, I want to implement iCloud synchronization between devices ... and my application requires an initial populated database.
The first time I run my application, it is going to populate my database with cloud and YES marks for some db'fields as "databaseInstalled". These fields are also synchronized in the cloud.
Now, when another device launches the application for the first time, I was hoping to get the "databaseInstalled" field to check if they are entering some information or not, but this is wrong ...
If databaseInstalled it is false, we enter data; if databaseInstalled it is true, we wait for iCloud synchronization.
The problem is that I retrieve the persistentStoreCoordinator asynchronously due to the fact that I do not want to block an application that is waiting for data to be loaded from iCloud ...
So, how can I find out a priori if I need to populate a database or it was populated on another device, and I just want to download a populated one from iCloud?
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if((__persistentStoreCoordinator != nil)) {
return __persistentStoreCoordinator;
}
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
NSPersistentStoreCoordinator *psc = __persistentStoreCoordinator;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *iCloudEnabledAppID = @"this is a secret!";
NSString *dataFileName = @"you do not have to know.sqlite";
NSString *iCloudDataDirectoryName = @"Data.nosync";
NSString *iCloudLogsDirectoryName = @"Logs";
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *localStore = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:dataFileName];
NSURL *iCloud = [fileManager URLForUbiquityContainerIdentifier:nil];
if (iCloud) {
NSLog(@"iCloud is working");
NSURL *iCloudLogsPath = [NSURL fileURLWithPath:[[iCloud path] stringByAppendingPathComponent:iCloudLogsDirectoryName]];
NSLog(@"iCloudEnabledAppID = %@",iCloudEnabledAppID);
NSLog(@"dataFileName = %@", dataFileName);
NSLog(@"iCloudDataDirectoryName = %@", iCloudDataDirectoryName);
NSLog(@"iCloudLogsDirectoryName = %@", iCloudLogsDirectoryName);
NSLog(@"iCloud = %@", iCloud);
NSLog(@"iCloudLogsPath = %@", iCloudLogsPath);
#warning to remove
if([fileManager fileExistsAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]] == NO) {
NSError *fileSystemError;
[fileManager createDirectoryAtPath:[[iCloud path] stringByAppendingPathComponent:iCloudDataDirectoryName]
withIntermediateDirectories:YES
attributes:nil
error:&fileSystemError];
if(fileSystemError != nil) {
NSLog(@"Error creating database directory %@", fileSystemError);
}
}
NSString *iCloudData = [[[iCloud path]
stringByAppendingPathComponent:iCloudDataDirectoryName]
stringByAppendingPathComponent:dataFileName];
#warning to remove
NSLog(@"iCloudData = %@", iCloudData);
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 lock];
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:[NSURL fileURLWithPath:iCloudData]
options:options
error:nil];
[psc unlock];
}
else {
NSLog(@"iCloud is NOT working - using a local store");
NSLog(@"Local store: %@", localStore.path);
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setObject:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
[psc lock];
[psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:localStore
options:options
error:nil];
[psc unlock];
}
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"iCloud routine completed.");
Setup *install = [[Setup alloc] init];
if([install shouldMigrate]) {
HUD = [[MBProgressHUD alloc] initWithView:self.window.rootViewController.view];
HUD.delegate = self;
HUD.labelText = NSLocalizedString(@"Sincronizzazione del database", nil);
[self.window.rootViewController.view addSubview:HUD];
[HUD showWhileExecuting:@selector(installDatabase) onTarget:install withObject:nil animated:YES];
}
else {
[[NSNotificationCenter defaultCenter] postNotificationName:@"setupCompleted" object:self];
}
[[NSNotificationCenter defaultCenter] postNotificationName:@"setupCompleted" object:self];
});
});
return __persistentStoreCoordinator;
}