Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iCloud doesn't work first time app is launched

For my app, I use iCloud key value storage to store some user settings. It syncs perfectly between my iPad and iPhone when both have the app installed. My issue is that when I delete the app, and I run it fresh, it doesn't have any of the settings from iCloud the FIRST TIME I run it. After I run it again, even though it didn't have the settings the first time, it has them.

I used some NSLogs to see what it sees in the key-value container, and the first time the app runs fresh it says "(null)", but any subsequent runs it prints out the NSArray that was saved previously.

I'll gladly provide code, but I'm not entirely sure what is relevant here.

I'd appreciate any help, this issue is driving me crazy...

like image 683
Daniel Gorelik Avatar asked Aug 16 '12 20:08

Daniel Gorelik


2 Answers

Add an observer for NSUbiquitousKeyValueStoreDidChangeExternallyNotification and sync NSUbiquitousKeyValueStore. Wait for the callback to be called soon.

if([[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil])
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyValueStoreChanged:)
                                                 name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification
                                               object:[NSUbiquitousKeyValueStore defaultStore]];

    [[NSUbiquitousKeyValueStore defaultStore] synchronize];
}
else
{
        NSLog(@"iCloud is not enabled");
}

And then use NSUbiquitousKeyValueStoreChangeReasonKey to distinguish between a first time sync and server change sync.

-(void)keyValueStoreChanged:(NSNotification*)notification 
{
    NSLog(@"keyValueStoreChanged");

    NSNumber *reason = [[notification userInfo] objectForKey:NSUbiquitousKeyValueStoreChangeReasonKey];

    if (reason) 
    {
        NSInteger reasonValue = [reason integerValue];
        NSLog(@"keyValueStoreChanged with reason %d", reasonValue);

        if (reasonValue == NSUbiquitousKeyValueStoreInitialSyncChange)
        {
            NSLog(@"Initial sync");
        }
        else if (reasonValue == NSUbiquitousKeyValueStoreServerChange)
        {
            NSLog(@"Server change sync");
        }
        else
        {
            NSLog(@"Another reason");
        }
    }
}
like image 78
erkanyildiz Avatar answered Nov 09 '22 04:11

erkanyildiz


There might be a delay between your app being installed (and launched) and KVS downloading the initial values. If you properly register to the change notification, you should see the values coming in.

Your code should always look like this, generally in your -applicationDidFinishLaunching: delegate method:

_store = [[NSUbiquitousKeyValueStore defaultStore] retain]; // this is the store we will be using
// watch for any change of the store
[[NSNotificationCenter defaultCenter] addObserver:self
      selector:@selector(updateKVStoreItems:)
      name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification
      object:_store];
// make sure to deliver any change that might have happened while the app was not launched now
[_store synchronize];
like image 23
Julien Avatar answered Nov 09 '22 04:11

Julien