NSUbiquitousKeyValueStore not so ubiquitous?

791 Views Asked by At

I am trying to store key-values with NSUbiquitousKeyValueStore. They seem to store fine while the app is installed, but if I delete the app off the device and run the app again, the key-values seem to be lost. Is this expected behaviour, or perhaps is there something I'm missing?

I am storing and retrieving values like so:

-(void)setString:(NSString*)stringValue forKey:(NSString*)keyValue {
    NSUbiquitousKeyValueStore *iCloudStore = [NSUbiquitousKeyValueStore defaultStore];
    [iCloudStore setString:stringValue forKey:keyValue];
    [iCloudStore synchronize];
}
-(NSString*)getStringForKey:(NSString*)keyValue {
    NSUbiquitousKeyValueStore *iCloudStore = [NSUbiquitousKeyValueStore defaultStore];
    return [iCloudStore stringForKey:keyValue];
}

What I've already checked:

  1. I have enabled iCloud and key-value storage in Target Capabilities.
  2. iCloud Drive is enabled on my device and the app itself is enabled.
  3. I have waited for some time before trying to load the values to be sure it wasn't just a syncing problem.
  4. I have registered an observer in the NSNotificationCentre as per Apple docs for NSUbiquitousKeyValueStoreDidChangeExternallyNotification. My observer is never called, on first run after install, or subsequent runs. My code(stripped back from Apple docs)

    NSUbiquitousKeyValueStore* store = [NSUbiquitousKeyValueStore defaultStore];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(updateKVStoreItems:)                                                         name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification
                                           object:store];
    [store synchronize];
    
    - (void)updateKVStoreItems:(NSNotification*)notification {
        NSLog(@"RECEIVED DATA");
    }
    

Additional questions -

  1. Is there a way of telling when your data has synced to the cloud?(i.e. uploaded data)
  2. Or the reverse, is there a way of telling when your app has synced successfully from the cloud?(i.e. downloaded data) I would have hoped that NSUbiquitousKeyValueStoreDidChangeExternallyNotification would notify for this, but since I'm not receiving this notification, I suspect it's just for when another device has updated the data while the app is open, a suspicion that seems to be confirmed by Apple docs:

    NSUbiquitousKeyValueStoreServerChange - A value changed in iCloud. This occurs when another device, running another instance of your app and attached to the same iCloud account, uploads a new value."

1

There are 1 best solutions below

1
On

Did you enable iCloud in the Application Services for the app id in the Apple Developer Portal? After that you also have to create a provisioning profile for the app.

The only difference I see in my code is the "name:" parameter. You need to specify that you want to observe NSUbiquitousKeyValueStoreDidChangeExternallyNotification

[[NSNotificationCenter defaultCenter]
 addObserver: self
 selector: @selector (storeDidChange:)
 name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification
 object: [NSUbiquitousKeyValueStore defaultStore]];

Your code throws a warning in my environment

Instance method '-addObserver:selector:object:' not found (return type defaults to 'id')

I also have been using setObject:forKey: instead of setString:forKey: