Abdalrahman Shatou
Abdalrahman Shatou

Reputation: 4748

iOS - NSUbiquitousKeyValueStore doesn't "actually" sync

I am using NSUbiquitousKeyValueStore to sync my application preferences and I am testing the sync process using two devices iPhone 3GS and iPhone 4.

As I change a preference in one device (say iPhone 3GS), it syncs the preference to NSUbiquitousKeyValueStore using the following code:

NSUbiquitousKeyValueStore *keyStore = [NSUbiquitousKeyValueStore defaultStore];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    [keyStore setObject:[userDefaults objectForKey:S_KEY_UI_SOUNDS]
                 forKey:S_KEY_UI_SOUNDS];

if ([keyStore synchronize]) {
    NSLog(@"TO ICLOUD - UI SOUNDS %@", [keyStore objectForKey:S_KEY_UI_SOUNDS]);
}

However two issues occurs:

First: although being registered for NSUbiquitousKeyValueStoreDidChangeExternallyNotification, I never receive it on iPhone 4. So if the iPhone 4 is active while the iPhone 3GS changes a preference, the iPhone 4 becomes unaware of it.

Second: As the iPhone starts to sync the preferences from NSUbiquitousKeyValueStore, it never gets the new preference set using iPhone 3GS (see code below). This is despite of a successfully synchronization with NSUbiquitousKeyValueStore (the synchronize method returns YES).

NSUbiquitousKeyValueStore *keyStore = [NSUbiquitousKeyValueStore defaultStore];
if ([userDefaults synchronize]) {
    NSLog(@"FROM - UI SOUNDS %@", [keyStore objectForKey:S_KEY_UI_SOUNDS]);
}

Is there a fix for that? or what am I doing wrong?

Upvotes: 3

Views: 3358

Answers (1)

Julien
Julien

Reputation: 3477

First -synchronize is not about "synchronizing with iCloud server". It's about synchronizing you changes and the local storage on disk. Once it's on disk, the underlying engine will push your changes to the cloud whenever it sees fit (generally after ~3s).

Second, you should subscribe to the store change notification.

In short, the first thing you should do when using NSUbiquitousKeyValueStore is something like:

store = [NSUbiquitousKeyValueStore defaultStore];
// subscribe immediately to any change that might happen to the store
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(storeDidChangeExternally:) name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:store];

// get any changes since the last app launch right now (safer)
[store synchronize];

Lastly, synchronization with the cloud happens at "proper time" (you can't control it for now).

Just to give you an idea, once you have "synchronized" your in-memory changes to the disk, the engine will generally start a synchronization with the cloud "soon" and push your changes.

The server will then push a notification to the other devices which will then schedule a synchronization with the cloud as well.

Under normal circumstances, it takes ~7s for devices to be in sync.

Upvotes: 4

Related Questions