Settings Sync

Syncing the settings between instances of your app, through iCloud, seems like a good idea.  And doing this automatically, by walking the contents of NSUserDefaults and syncing them seems like a good idea.  Until you realize that what goes into NSUserDefaults isn’t just your own stuff.

In my Unicode Character Viewer app, I was using MKICloudSync to do this automatically.  Recently I received a bug report, with a crash dump that indicated a crash:

Unicode[280] <Error>: *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘NSUbiquitousKeyValueStore: key ‘ Output Device audio0′ is too long.’

iCloud Key Value Store has a maximum key length of 64 characters, and a key in my NSUserDefaults is exceeding that.  The key is “ Output Device audio0”, which I didn’t put there.

Turns out Apple uses NSUserDefaults to store all kinds of things.  I just did a quick dump of the settings in my app, and here’s what I found:

AirPlayShouldShowDebugButtonInPicker: 1
AppleITunesStoreItemKinds: (...)
AppleKeyboards: (...)
AppleKeyboardsExpanded: 1
AppleLanguages: (...)
AppleLocale: en_CA
NSInterfaceStyle: macintosh
TVOutStatus: -1

And 119 (!) keys related to WebKit settings.

NSInterfaceStyle is an interesting one.  The values for this enumeration are:

typedef enum {
  NSNoInterfaceStyle = 0,
  NSNextStepInterfaceStyle = 1,
  NSWindows95InterfaceStyle = 2,
  NSMacintoshInterfaceStyle = 3
} NSInterfaceStyle;

How the heck did this make it into iOS?

Anyway, clearly some of these should not be sync’ed between devices, as they’re Apple private settings that are specific to the device you’re on.  The MKICloudSync method is not a good way to sync settings between devices without some sort of filtering to sync only the keys your application creates.