views:

66

answers:

3

Hi,

I am using the NSUserDefaults' api -registerDefaults api to register the factory defaults of my application. All is fine for the first version of the application. But when I provide an update for the iPhone application, I have 3 criteria to make sure:

  1. The user preferences of older version app should be intact.
  2. Addition to the factory defaults specific to the new version should be applied.
  3. Providing flexibility in the design to the future version updates so that the user defaults modifies itself based on the new version.

The api -registerDefaults does not register factory defaults in new version updates because a plist file containing user preferences already exists in the /Library/Preferences of sandbox. And in case if we reset the preferences with new factory defaults, user preferences of previous version will be lost.

I think there should be a design pattern to handle such cases, so in general how do we cater with such situations? Doesnt Apple provide any inherent support for this? Or am I missing some links, I tried googling around without any success.

Thanks, Raj

A: 

What is the problem? If the user never changes (or more exactly: sets) a preference, the factory default will be used. If an update of your app changes the factory defaults, those will be used instead. If the user has set his own preference, that will continue to be used.

A new factory default doesn't (and shouldn't) overwrite an user set preference. NSUserDefaults does exactly what you seem to be after.

Johan Kool
I have a list of items to be displayed which I maintain in user defaults, in the first version there are say 10 items. I mainly maintain them in preferences so that the order of that items, if at all user changes them, should be updated for the next launch. Now in the new version, say I have added 2 more items. The total items are 12 now. If I use -registerDefaults with 12 items now, the 2 items wont be added because preferences plist already exists! That would be disastrous as the number of items are not updated in the new version. Besides, items is just one aspect of it.
Raj
A: 

I agree with Johan Kool. User defaults work as they should. If there's a preference that you want changed (for whatever reason) in an updated app version, just slightly rename the preference. For example, if someValue was a preference in version 1, then in version 2 name it someValue_v2 and your new factory default will take effect.

regulus6633
+1  A: 

If this list of items you're talking about is an array registered under a single key, then yes, a larger array passed to -registerDefaults: will be ignored in favor of the smaller array stored in the persistent plist. NSUserDefaults tracks stuff on a per-key basis, and doesn't do any interpretation of the contents you store in there, so it's not going to try to automagically merge previous array values with new array values, or anything daft like that.

If you want new items to be added to this array by default when the user upgrades, I would recommend adding the items explicitly to the key yourself by fetching the existing array, adding the new items, and then saving the larger array back to the user defaults again. You can use a separate boolean flag to indicate that the upgrade has been done, to ensure that the addition doesn't get performed multiple times.

Brian Webster
This is exactly the problem faced by me. I have thought of your approach by explicitly maintaining a bool to indicate that upgrade is done, rather I have tried to maintain an application version in user defaults. Now one more hurdle is - In my basic version of app there are 10 items, if I add 2 items in v 1.1 and 2 more in v1.2, and if user tries to update directly to v1.2 without going through v1.1, he misses the items of v1.1, so I would internally update to v1.1 and then to v1.2 in such cases. But is this the standard everybody follows? How does other applications tackle this problem? Thanx
Raj
I don't know how "standard" you'd consider it, but I've used this pattern at least once before. Another slightly easier way to do it would be to just blow away any custom reordering the user had done, and just set the entire array upon upgrading rather than trying to just add the new objects piecemeal. Less user friendly though.
Brian Webster
Yeah, the second approach is less user friendly, apart from that it will also blow up all other settings. Its better I would opt for the first approach. Thanks for suggestions.
Raj