iPhone - upgrading from old app preferences
Asked Answered
E

1

0

If I build a 1.0 app with 2 strings in the defaults, using registerDefaults.
And in a 2.0 version, I decide to remove the first old string, and move the second one (changing its key string) with a new third one into an array.
How may I deal with this and how to deal with the changes that could have been made to the content through versions.

1.0 Prefs should be

StringKey    someValue  
DateKey      10/10/2010

1.1 Prefs should be

StringKey    someValue  
DateKey      2010/10/10

2.0 Prefs should be

Array  
    Item0 is    DateKey        10/10/2010  
    Item1 is    BadString      BadBadValue
Ex answered 26/3, 2011 at 15:21 Comment(0)
V
1

If you've used registerDefaults: in version 1.0 of your app it's easy. When you stop to register those old values and they were not changed by the user they disappear from NSUserDefaults.

So ask NSUserDefaults for all objects that should be converted. If they exist convert them to the new format, save them in the NSUserDefaults and remove the old value.

Something like this should work

// check if you can get the old object. if it's there it was changed by the user
if ([[NSUserDefaults standardUserDefaults] objectForKey:@"OldKey1"]) {
    // old key is present
    id oldObject = [[NSUserDefaults standardUserDefaults] objectForKey:@"OldKey1"];

    id newObject = ... // convert the old object to the new object
    [[NSUserDefaults standardUserDefaults] setObject:newObject forKey:@"NewKey1"];
    [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"OldKey1"];
}
else {
    // old key not there, do nothing
}

// register your new defaults...

If you haven't used registerDefaults: you have a problem now. Because you don't know if the object was changed by the user or if the object is simply your default. And you can't assume that the value is still in default state just because it has the same value as the default.

But what to do in this case? I would probably reset the value to default and show a UIAlert that tells the user to check the preferences because I did a mistake :-)

Various answered 26/3, 2011 at 15:46 Comment(8)
@fluchtpunkt : Great. That's the way I started to write the code. But How do you deal with the prefs version. I planned to add into the plist the prefs version. Because when you're on 8.5 version, you must know which version of prefs you are reading to know which keys to call and how to interpret their content. Because you can have a KeyCodeAAA used in the 1.0 version that does not contain the same content thing or format that the KeyCodeAAA used in the 3.2 version (see my edit about the dates (it could be anything else). Let's imagine the users changed the date and you're running a 2.0 app).Ex
sure, add the version to the preferences. This is one of the few exceptions where you can't use registerDefaults. Oh and if you want to save dates you should probably save NSDate objects.Various
@fluchtpunkt : how to you deal too with old keys that collides with new defaults keys that does not have the same content or format ? You init them with the default values at start, but when you want to know if an old value is present, you just override your current value if present. But you cannot know if the objectForKey returned value is the old one or the new one, or you must test all the values with the new ones to see if they are different... How do you deal with this ?Ex
you are right. you should do the upgrade before you register the new defaults.Various
@fluchtpunkt : Yes, but doing this way now, new default will override old ones you've just loaded. Must of all if you init new defaults from a plist file included in the main bundle. Doing this way, you must test all existing values before registering default, so I'm asking the usefulness of these default. Isn't it ?Ex
defaults don't overwrite values. NSUserDefaults works with different domains. When you register defaults you store them in the RegistrationDomain when you change values they are saved in the application domain. If NSUserDefaults can't find a value in the app domain it takes the value from the registration domain. Simplified: when you register defaults they are saved in a different object. They don't interfere with values from the app domain. They are completely separated.Various
@fluchtpunkt : I understand this but objectForKey don't tells you from where the returned value comes from. So If I load defaults, and get a @"wantThisFeature" key with @"DoIt" value. Then I load the defaults from a plist into which there is also this key, with @"I want a rabbit" value, but @"DoIt" does not have sense anymore, or have a different sense. What should I do to make the things work fine ? Just delete the @"wantThisFeature" key ?Ex
@fluchtpunkt :Other problem : if I want to fill an array, and the user had set only the item 2 in the old prefs. At start, if I don't load the default prefs first, I don't know how many items are in this array. So how may I insert the item 2 into an array that I don't know the size ? What if I want to move this item2 in item3 into new prefs... That looks like a nightmare :-)Ex

© 2022 - 2024 — McMap. All rights reserved.