Hard CoreData + iCloud Script

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;

    // Set up iCloud in another thread:

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // ** Note: if you adapt this code for your own use, you MUST change this variable:
        NSString *iCloudEnabledAppID = @"this is a secret!";

        // ** Note: if you adapt this code for your own use, you should change this variable:        
        NSString *dataFileName = @"you do not have to know.sqlite";

        // ** Note: For basic usage you shouldn't need to change anything else

        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);

            // da rimuovere

            //[fileManager removeItemAtURL:iCloudLogsPath error:nil];
            #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];

            //[fileManager removeItemAtPath:iCloudData error:nil];
#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:@"icloudCompleted" object:self userInfo:nil];
            [[NSNotificationCenter defaultCenter] postNotificationName:@"setupCompleted" object:self];
        });
    });

    return __persistentStoreCoordinator;
}
+3
source share
3 answers

You cannot know if data will be available in iCloud until you finish synchronizing with iCloud. This means that you have two options:

  • Wait for synchronization to complete.

  • Launch your default database and change your changes from iCloud whenever possible.

iCloud , , . , , - : , , .

0

.

iCloud + CoreData - ?

100% . , , 100% ( , ).

, , .

0

, , . , iCloud Core Data store. , iCloud - , , . , , ( , ), iCloud .

, :

  • , .
  • Be able to identify pre-filled records and distinguish them from user-entered.
  • Start the deduplication process every time iCloud receives new transaction records.
  • Only record seed data once per device / account combination.

You can read more here: http://cutecoder.org/programming/seeding-icloud-core-data/

0
source

All Articles