Just wrote this class, MKiCloudSync (100 lines of code) that auto syncs your NSUserDefaults to iCloud.

How to use?

All you need to do is to enable iCloud key value store entitlements, copy the files and forget about the rest.

Step 1:

Enable iCloud entitlements for your app. This is easily done in Xcode 4.2.1 by opening your target settings and checking “Enable Entitlements” from the summary tab.


This is illustrated below.

Xcode

Enabling iCloud Entitlements in Xcode 4.2.1


Tip:
If you are sharing settings with other apps, ensure that your iCloud Key-Value Store is the same across all those apps.
Step 2:
Drag the two files

  • MKiCloudSync.h
  • MKiCloudSync.m

into your project. You can find these files in the Source Code section of this post.
Step 3:
In your applicationDidFinishLaunchingWithOptions: method,
start the sync by calling,

[MKiCloudSync start];

You also have to #include the header file.
This is probably the only line of code you have to write!
Step 4:
Sleep… Kidding.

There is no step 4. Continue using NSUserDefaults to save your settings. The MKiCloudSync class automatically syncs your settings to iCloud and restores them back to your NSUserDefaults when they are changed on other devices.


To top them all, it also posts a notification,

kMKiCloudSyncNotification

to let you know that a sync has been performed. You can listen to this notification and update your user interface from NSUserDefaults.

Advantages

  • Upgrading your existing iOS 4 apps to sync settings to iCloud is now super easy.
  • With this class, you no longer have to add calls to NSUbiquitousKeyValueStore throughout your app. You can continue your existing method of saving them to NSUserDefaults. Everything is automatic. If your settings might change often, you can observe the notification kMKiCloudSyncNotification and update your user interface.

Source Code

Licensing


Royalty free for commercial or non-commercial use, though attribution will please me to write more such code :)


Mugunth

Follow me on Twitter

  • Yanivka

    Great stuff :)
    Now i can really go to sleep ;)

    is it possible to do it in the same simplicity for syncing files as well? (user data/sqlite file)

    thanks again,
    Yaniv

    • Anonymous

      Conflict resolution for files depends on the app.

      • Yanivka

        ok, it doesn’t have to be THAT simple, it could have a delegate function that i have to implement in order to resolve conflicts..

        a simple guide on how to use icloud file sync properly could help as well ;)
        but i always like to use those one line packages that hides the ugly code..

        Yaniv

        • Anonymous

          Interesting. I’ll try that.

          • Yanivka

            thanks!

  • http://sgleadow.github.com Stewart Gleadow

    Thanks for the post. It looks like other comments have already touched on conflict resolution.

    Is there no conflict resolution for the key-value store? Is it just a last-writer-wins policy if two apps are writing the same keys?

    • Yanivka

      yes, Apple’s documentations states that the key/value store is “last-writer-wins”.. (as opposed to file syncing)

      • Anonymous

        Yes, it could probably because, key/value stores too little information to make an educated guess if at all there is a conflict.
        Mugunth
        Pre-order my iOS 5 Programming book
        http://mk.sg/ios5book

        • Peter Johnson

          Book ordered

  • http://www.kypselia.com/ KPM

    Great, thanks! Now we really have no excuse not to implement iCloud synchronisation. 

  • http://twitter.com/icode2020 bharath2020

    There is nothing great about the piece of code, But I like the simplicity it offers.. Good job Mugunth..

  • Moomio

    Followed the directions exactly as followed, doesn’t seem to be working.  How long does iCloud take to sync the devices?  How does it know which device has the latest version of the data to sync if the connection to the internet is slow or something else hangs up the transfer?

    Bigger question, if you only call the [MKiCloudSync start]; when the appdidfinishlaunching, if you make changes after playing the around with the app for an hour but don’t restart it, how does MKiCloudsync know that changes were made?  Am I supposed to restart the app to start the sync so that my other device sees the changes?

    Just curious

    • Anonymous

      You should see the changes in approx 30 sec max.

      If you don’t, your iCloud entitlements are wrong.

      On your second question.,
      iCloud pref sync doesn’t bother about “merge”
      Latest data “wins”

      Your question is valid only for files. That’s why pref sync was doable in “1 line” code :-)

  • Moomio

    Can’t edit previous comment, but MKiCloudSync did work with my app which uses all NSUserDefaults to save player preferences and game progress.  Unfortunately, the delay may be in part that NSUserDefaults are a bit sluggish, and could be due to internet stability.  It still took about 10 minutes to sync my devices. 

    The question and issue still remains, what if two people play the same app on two different devices, which will it sync? Off to experiment now! 

    • Anonymous

      It syncs the “latest”, the latest value wins.

    • Anonymous

      If they are logged in to different iTunes accounts, it doesn’t even sync

  • Moomio

    Hey MugunthKumar!   Thanks for the replies, maybe our conversations on here will help others.

    So here is what I have discovered after extensive ‘playing’ around last night.  First off, I have a fully functional App on the market (DuggedUp) that I’m playing around updating to iCloud.  So, familiar with entitlements, sandboxing, etc.

    If I implement MKiCloudSync in the applicationDidFinishLaunchingWithOptions: method, then obviously, that is when it is called, and the cloud pulls down the data.  So here is the issue, “when” does applicationDidFinishLaunchingWithOptions: method get called.   It gets called when the app is first booted up…and only when the app is first booted up.  That is the issue I was having.

    On my iTouch devices when you play an app for a while and then set it down, the app remains running in the background of the device.  ie.  when you hit the home screen, the app doesn’t ‘quit’ entirely.  When you come back and tap the app icon, it just pulls it out of memory and into the foreground.  So when I went back to the app, the applicationDidFinishLaunchingWithOptions: method was not called yet or more precisely, again….and therefore, no iCloud update. 

    So in order to get iCloud to pull the data, I actually had to double tap the home button and then force close my app from the ‘dock’.  Then when I restarted the app, it downloaded the iCloud data.

    I am concerned that many of my users are not going to want, know how, or remember to do this on a regular basis. 

    Are there other places in the code that you could call [MKiCloudSync start];?   What are your thoughts.

    Thanks!

    • Toby Brennan

      Hey,

      I realise it may be a bit late, but I would suggest putting it in the appDelegate applicationWillEnterForeground method. This is called every time the app is opened (even if already running). You could also place in applicationDidEnterBackground to sync when the close the app.

  • Michary

    Thanks for the code.

    Unfortunately it doesn’t work for me, I get an SIGARBT in line 41.

    Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘NSUbiquitousKeyValueStore: key ‘com.apple.audio.CoreAudio.HogMode.Owner-WM8758 Output Device audio0′ is too long.’Any clue what’s this about?Thanks in advance

    • Gustavo Tandeciarz

      I am seeing this as well… thoughts? 

  • http://twitter.com/jstewartdev Josh Stewart

    Awesome, fantastic help

  • Gustavo Tandeciarz

    Have you seen this issue:

    Error on start:
    Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘NSUbiquitousKeyValueStore: key ‘com.apple.audio.CoreAudio.HogMode.Owner-WM8758 Output Device audio0′ is too long.’

    • NLA

      I’m getting “Key … is too long” too….

      Any ideas???

      • http://www.appulize.com Maciej Swic

        Key length limit in this store is 64 utf8 chars. I have suggested adding a filter for key length.

  • Shaktising Pardeshi

    Hi MugunthKumar,
    I want to sync the NSUserDefaults data only to my iCloud account and want to retrieve from there. 
    What are the changes I have to make in your code to achieve this?
    Please help…

  • Cianiandrea10

    Is this file compatible with iOs 5? Because I alway have an error in compile time:

    Undefined symbols for architecture i386:
      “_OBJC_CLASS_$_MKiCloudSync”, referenced from:
          objc-class-ref in AppDelegate.o
    ld: symbol(s) not found for architecture i386
    clang: error: linker command failed with exit code 1 (use -v to see invocation) Could you help me ?! :(

    • Cianiandrea10

      Fixed… Thank You for your fantastic code!!

      • mike

        how you fixed it?

        • Davis

          How did you fix it? It’s really bad practice to talk about a problem and then never post a solution. Here I am 3 months later with the same problem, and this is the only mention of it.

          • Guest

            Make sure both .h and .m files are added in Targets > Build Phases > Compile Sources

      • Davis

        How did you fix it? It’s really bad practice to talk about a problem and then never post a solution. Here I am 3 months later with the same problem, and this is the only mention of it.

  • Lisa

    Amazing! Thank you so much!

  • http://twitter.com/iphonetest11 test

     Hello,
    I am developing an app using iOS5, It has functionality to import and export data from iCloud & dropbox both.
    But import and export operation is manually when ever user wants they can import & export local data(store in core data such as user info Name,Number and address).
    and that data will populate in app.

    Will you help me how can i proceed with this?

  • John Wickham

    This is awesome, works great! Except the notification. I set it up to observe the kMKiCloudSyncNotification in my viewDidLoad but when it actually does sync, the notification is not triggered. Any ideas?

  • http://www.appulize.com Maciej Swic

    Hey mate, you need to add a check for key length when adding stuff to iCloud. Max key length is 64 utf8 chars, or the app crashes. I have logs of com.apple.audio.CoreAudio.HogMode.Owner-WM8758 Output Device audio0 in flurry which just breaks that limit!

    Edit: That key is nothing my app added, seems Apple internal and nothing i can control. So MKiCloudSync definitely needs a check there!