Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSUserDefaults objectForKey sometimes nil

I've just noticed that a key that exists in my **NSUserDefaults** is returning nil quite often. It seems about half the time it's correct and the other half it's not. I say half the time, but I dont mean that its flip-flopping, its just 40-50% I see it not work. When I write the initial value, I call synchronize immediately. I use this key as the applications revision I set when a new user signs up.

The following code returns nil:

#define kDBrevision  @"revision"

NSString *rev = [[NSUserDefaults standardUserDefaults] objectForKey:kDBrevision];

When I launch the app and just monitor the value (without writing any NSUserDefaults), the value sometimes is valid with no modifications to the NSUserDefaults at all.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSString *r = [[NSUserDefaults standardUserDefaults] objectForKey:kDBrevision];
    NSLog(@"revision %@", r);
    _exit(1);

I have no idea why this is happening. Im running iOS 10 on my device connected to Xcode 8.2.1. Anyone have any ideas? Thanks

EDIT: I started talking to apple about fixing this and found out that if you have file protection complete turned on, it can be the cause of this issue showing up from time to time, however apple told me that my particular case (which is the only one I was sure of at this time) is a bug. The case is when you use Xcode to launch the app on the device it should not fail like this and it occasionally does. No idea when or if it will be fixed. Instead I moved my critical strings from the defaults to the keychain instead.

like image 396
Tim Avatar asked Jan 20 '17 04:01

Tim


2 Answers

This appears to be an Xcode 8 and/or iOS 10 bug. I ran into it myself and conclusively narrowed the case to UserDefaults intermittently returning nil when in fact there was data for the key. Specifically, I set the data once, then removed the set logic and executed only the get logic, repeatedly, and sometimes got values, sometimes got nil.

I changed my Run scheme to use Release configuration and ran the app on device without the debugger attached and the issue disappeared, that is, the get logic produced the correct value every time I executed it (~30 times).

Here is some more discussion:

iOS 10 with XCode 8 GM caused NSUserDefaults to intermittently not work

iOS 10, NSUserDefaults Does Not Work

https://forums.developer.apple.com/thread/48700

https://forums.developer.apple.com/message/143155#143155

like image 173
bgfriend0 Avatar answered Sep 27 '22 23:09

bgfriend0


try below code in didFinishLaunchingWithOptions

Swift 3.0

UserDefaults.standard.synchronize()

Obective - C

[[NSUserDefaults standardUserDefaults] synchronize];
like image 30
Bucket Avatar answered Sep 27 '22 23:09

Bucket