NSUserDefaults might be NULL when app is launched

Dear all,


We have a universal application which we save some trivial information in NSUserDefaults. When the app is launched, we should definitely read some value from NSUserDefaults. We have hundreds of iPad and iPhone users; but in some iPhone users (a very very small portion), all values in [NSUserDefaults standardUserDefaults] might be NULL when app is launched. Removing app from the background and re-opening it solves the problem.


This happens in iOS9 and iOS8 as well, where app is built with iOS8.


Is this a bug known from Apple?


Thanks,

Replies

Is it possible that it's not so much that the values are all null, but that the api is temporarily broken and returning null. For distinction, if you find the defaults are null and try writing a non null value and then reading it back, do you get null or the written non null value?


I am having the problem of randomly and rarely just getting nulls, even if I've set a value, on OSX.


I suspect that my situation occurs sometimes after deleting the app sandbox, possibly before actually shutting the app down. I can only clear it by restarting the Mac.


iOS users typically restart their devices rarely. So I'm wondering if your small percentage of users with a problem could be ones who have deleted and reinstalled the app (possibly while the app was running), since they last did a full restart.

Is your app being launched into the background after reboot before first unlock? (e.g. significant location change, background fetch) NSUserDefaults is currently backed by a file on disk with file protection set to NSFileProtectionCompleteUntilFirstUserAuthentication, I believe, so any attempt to access NSUserDefaults before the user has unlocked their device will return nulls. I thought I heard reports of it even overwriting the existing valid defaults with nulls in that case.


If this is what's happening, you need to add code to check for whether or not protected data is available when your app is launched into the background, and do not attempt to access defaults if not.


p.s. You posted this in Cocoa, but your question is clearly asking about iOS (Cocoa Touch). You may want to move the thread to a more appropriate forum.

First thing is that, when all the values are null, we can set new values and read them properly.

The second thing is I am sure that this problem is not caused by deleting and reinstalling (Some of those people having this issue work in our company)

Hi junkpile,

Our application is monitoring some regions and beacons and is a VoIP application as well (VoIP feature has been added after this issue arised). When this problem initially happened, I tought it could be due to backgrounding issue, but right after I have noticed that the same problem could happen in some iPhones who don't absolutely have region monitoring and so there seems no reason to being launched into background.

In addition, I tried several test procedures, restarting a phone and launching it to background without authenticating phone. I never could re-generate such an issue systematically. It doesn't occur totally randomly; a person having this issue, meets it regularly. And most of the people never meets this issue.

Btw, I meet with the issue of overwriting NULL values with existing at one phone. But cannot regenerate the problem systematically.

May you suggest any procedure to follow to create this problem again?

Thanks!

You're asking "How to I recreate this system-level race condition?" 😟


I don't know which version of the VoIP system you're using, but the old VoIP system has the same potential problem as the region monitoring system, because the problem is the same underlying mechanic: Applications that get restarted upon device restart can be relaunched before data protection is lifted.


So the remedy is the same: You need to add in code to wait for protected data to be available.


Probably one of the important factors is that I believe this is more likely to happen when the device has a passcode configured. Without a passcode configured, data protection is lifted sooner.

Do you have any updates on this? We seem to be experiencing the same issue:


1) It seems to affect the same user (using an iPhone 5s running iOS 9.3.2) over and over again

2) We use complete data protection for our app

3) When this issue manifests, we seem to be getting null back when accessing a specific key in [NSUserDefaults standardUserDefaults], but when restarting the app, there is a valid value there.

4) We access this key in -[UIApplicationDelegate applicationDidFinishLaunchingWithOptions:] to determine whether to show our login screen or take the user into the logged in experience.

We had same issue, I now have this when launching App, and seems to solve the problem.


I have similar code for re-entering the App.


-cris

-----------------------


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

BOOL protectedDataAvailable = [UIApplication sharedApplication].protectedDataAvailable;

if (protectedDataAvailable == YES) {

[self launchApp];

} else {

NSLog(@"protected_Data_NOT_Available");

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(protectedDataAvailableNotification:) name:UIApplicationProtectedDataDidBecomeAvailable object:nil];

}

return YES;

}


- (void) protectedDataAvailableNotification:(NSNotification*) notification

{

NSLog(@"protectedDataAvailableNotification");

[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationProtectedDataDidBecomeAvailable object:nil];

[self launchApp];

}

Anyone have any joy? I'm still seeing it in iOS 10.1


Just posted some interesting things I've seen here: https://forums.developer.apple.com/message/135342


Including the very odd thing I saw today where data from 2 years ago, that had been very much deleted, was resurrected in one of my apps... is iCloud misbehaving??

I am really frustrated... It's affecting my app as well. It's was good for half a year now, and now it starts happening again. And when it happens in my apps, it's also happening in other Apps (logged out of Slack, WhatsApp, Youtube, ...)


Would be great if Apple could really have a deeper look into it!!!

Thanks for this solution Cris. I think we are running into this same problem with the keychain not always being available when the app is launched. Have you verified from your user's app logs that this is sometimes the sequence of events (the protected data becomes available after the didFinishLaunchingWithOptions notification)? My only concern is if the protected data is not available in didFinishLaunchingWithOptions but the UIApplicationProtectedDataDidBecomeAvailable does not fire, so the app never finishes initalizing.

This happens due to Apples data protection policy which is at some level obscure. I have been using an workaround so far which is working consistently. When app's launched check if keychain is inaccessible or not, if inaccessible just kill your app.

Code Block
+(BOOL) isKeychainAccessible
{
NSString *keychainAvailablilityTestKey = @"keychainAvailablilityTestKey";
NSString *keychainAvailablilityTestValue = @"keychainAvailablilityTestValue";
[self createKeychainValue:keychainAvailablilityTestValue forIdentifier:keychainAvailablilityTestKey];
NSString *loadedValue = [self keychainStringFromMatchingIdentifier:keychainAvailablilityTestKey];
[self deleteItemFromKeychainWithIdentifier:keychainAvailablilityTestKey];
return ([keychainAvailablilityTestValue isEqualToString: loadedValue]);
}