NSUserDefaults objectForKey sometimes nil

2019-04-30 03:36发布

问题:

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.

回答1:

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



回答2:

try below code in didFinishLaunchingWithOptions

Swift 3.0

UserDefaults.standard.synchronize()

Obective - C

[[NSUserDefaults standardUserDefaults] synchronize];