tags:

views:

253

answers:

1

Retrieving a value from standardUserDefaults using integerForKey after saving with setInteger:forKey always crashes app.

If I retrieve value using objectForKey and cast value to int, there are no errors and I can display value in a log message fine. However, when I attempt to assign that int to another int or try to perform a math function on it, like adding, it crashes app as well.

How do I retrieve an int that I've saved to standardUserDefaults? I'm developing against SDK 3.0 but have experienced identical issue in 2.2.1. Thanks.

prefs defined as

NSUserDefaults *prefs;

and retrievePrefs always called before savePrefs. App also calls [prefs synchronize] before exiting.

-(void)retrievePrefs {
    prefs = [[NSUserDefaults standardUserDefaults] retain];
    if (prefs) {
       // doesn't crash app, spits out 'page: 1'
       NSLog(@"page: %@", [prefs objectForKey:@"pageIndex"]); 

       // crashes app with no details
       NSLog(@"page: %@", [prefs integerForKey:@"pageIndex"]); 
    }
}


-(void)savePrefs {
    if (prefs) {
     [prefs setInteger:1 forKey:@"pageIndex"];
    }
}
+3  A: 

Your second NSLog call is what's causing it: the %@ qualifier is used to print out Objective-C objects or CoreFoundation CFTypeRefs, so it's interpreting that integer as a pointer and attempting to dereference it.

What you need is:

-(void)retrievePrefs {
    prefs = [[NSUserDefaults standardUserDefaults] retain];
    if (prefs) {
        NSLog(@"page: %@", [prefs objectForKey:@"pageIndex"]);
        NSLog(@"page: %ld", (long)[prefs integerForKey:@"pageIndex"]);
    }
}

Check the API documentation for NSLog, printf, and -[NSString stringWithFormat:] for more information.

Jim Dovey
Thanks for the amazingly quick and correct response! The (long) did the trick. I tried using (int) before but that didn't help and the app continued to crash. Would you mind explaining the difference between long and int as it relates to setInteger:forKey and integerForKey?Thanks again! Have been butting my head against this issue for a bit.
sam
ok thanks. looks like the log statement was indeed causing the crash and i was mis-attributing the crash to other things, like integerForKey not working properly.
sam
The setInteger: uses the NSInteger type, which is defined as a 32-bit integer in 32-bit apps and a 64-bit long in 64-bit apps; i.e. it's always the size of a processor register.As regards the cast, casting to long will yield a 32-bit value in 32-bit processes, and a 64-bit value in 64-bit processes, therefore it will match the size of NSInteger. It's also precisely what Apple recommends for passing NSInteger or NSUInteger to a printf-style function.
Jim Dovey