1

I have an app already in the AppStore that uses NSUserDefaults. Some of the defaults are Default settings that I go ahead and set when the app is first launched, and then the user is allowed to change them later if they wish. So, in my AppDelegate appDidFinishLaunchingWithOptions I put:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

if (! [defaults boolForKey:@"notFirstRun"]) {

    [defaults setBool:YES forKey:@"notFirstRun"];

    [defaults setInteger:0 forKey:@"verseKey"];
    [defaults synchronize];
}

The issue I am having now is I want to add some more Default settings in the NSUserDefault category, so I want to make it look like this:

 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

if (! [defaults boolForKey:@"notFirstRun"]) {

    [defaults setBool:YES forKey:@"notFirstRun"];
    NSString *smalltitle = @"4";
    NSString *smallarticle = @"3";
    [defaults setObject:smalltitle forKey:@"Title"];
    [defaults setObject:smallarticle forKey:@"Article"];
    [defaults setInteger:0 forKey:@"verseKey"];
    [defaults synchronize];
}

I know that this will cause an issue for those who have already downloaded the app, and are merely updating it. They will not run that code because the notFirstRun Bool has already been set to YES. Any thoughts on what I should do here?

Matthias Bauch
  • 89,811
  • 20
  • 225
  • 247
user717452
  • 33
  • 14
  • 73
  • 149

3 Answers3

6

The proper solution is to not actually populate NSUserDefaults with default values. Instead, use the registerDefaults: method.

At app startup you do:

NSUserDefaults *default = [NSUserDefaults standardUserDefaults];
[defaults registerDefaults:@{
    @"Title" : @"4",
    @"Article" : @"3",
    @"verseKey" : @0
}];

That's it. Call this every time the app is run. These defaults are not actually persisted. The value is only returned if there isn't already an explicit value for the key. You can update these defaults all you want without affecting any existing values.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
0

Make a new notFirstRun Boolean value (i.e. notFirstRunTwo). That will be 'NO' for existing users, too.

Sarreph
  • 1,986
  • 2
  • 19
  • 41
  • 1
    Not sure who marked down this answer, but for what my issue is and what I described, it is the simplest. – user717452 Nov 24 '12 at 22:30
  • 1
    and in the 10th Version of your app you simply add `notFirstRunTen`. Registering defaults is superior because of exactly that problem. Another thing is that with registering you can actually change the default values for existing users. With the `firstRun` method you can never distinguish between values that were set by the user and values that were not touched by the user. Btw, I didn't downvote. – Matthias Bauch Nov 25 '12 at 12:19
  • @MatthiasBauch That would only happen if I constantly add in new features that require new defaults to be set. If I don't, all new updates would work with just those two keys. – user717452 Nov 26 '12 at 20:19
  • 1
    From my experience this is exactly what will happen. You will add more settings in future versions. And you want to change the default values of existing values too. I did that more than a single time. But feel free to do it however you want. I only learned about `registerDefaults:` after I made the firstRun mistake. Don't go for simple if better is just a tiny bit harder and will be more simple in the future ;-) – Matthias Bauch Nov 26 '12 at 21:58
0

I suggest to do the following :

  • check userdefaults for stored app version if it is equal to the current or not , if not.
  • store the current app version and do your first launch initialization

    the code

`

 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
 NSString *appVersion = [NSString stringWithFormat:@"%@",[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]];

 if (! [defaults objectForKey:appVersion ])
 { 
  /// store the current version and then do your first run functions
      [defaults setObject:[NSNumber numberWithInt:1] forKey:appVersion];
   /// here do your first run
 ......
 }`
Omar Freewan
  • 2,678
  • 4
  • 25
  • 49