We are currently experiencing the following weird issue with our iPhone app. As the title says, NSUserDefaults
is losing our custom keys and values when phone is rebooted but not unlocked, and this is happening on a very specific scenario.
Context:
We are using the NSUserDefaults
in the app to store user data (e.g. username).
Our app has Location enabled on Background Mode.
We are experiencing this issue only when distributing over the air or by Testflight. If I drag and drop the .ipa (same that was distributed over the air) into my phone using Xcode I don't experience this issue.
Situation: The user installs the app, logs in and the username is stored on the NSUserDefaults
successfully. Then, the user switches OFF they device and turns it back ON and lets the phone sit around for some time before unlocking the screen.
Problem: If in that time a significant location change is triggered, the app comes to live on background but the NSUserDefaults
is empty (Only has some keys from apple but none of our custom keys). Then, the NSUserDefaults
never gets this keys recovered no matter what you do (e.g. if you unlock your phone and open the app you will see the keys are still missing).
Any help or idea will be truly appreciated :)
I was having a very similar issue. Background the application. Use other memory heavy applications till my application gets jettisoned from memory. (You can observe this event if you have your device plugged and xcode running the build. Xcode will tell you "application was terminated due to memory pressure). From here if your application is registered for background fetch events, it will wake up at some point and get relaunched but into the background. At this point if your device is locked, your NSUserDefaults will be null.
After debugging this case for days, I realized it wasn't that NSUserDefaults was being corrupted or nilled out, it was that the application has no access to it due to device lock. You can actually observe this behavior if you manually try to download the application contents via xcode organizer, you'll notice that your plist which stores the NSUserDefaults settings is no present if your device remains locked.
Ok so NSUserDefaults is not accessible if application is launched into the background while device is locked. Not a big deal but the worst part of this is, once the application is launched into the background it stays in memory. At this point IF the user then unlocks the device and launches the application into the foreground, you STILL do not have anything inside NSUserDefaults. This is because once the application has loaded NSUserDefaults into memory (which is null), it doesn't know to reload it once device becomes unlocked. synchronize does nothing in this case. What I found that solved my problem was calling
[NSUserDefaults resetStandardUserDefaults]
inside the applicationProtectedDataDidBecomeAvailable
method.
Hope this helps someone. This information could have saved me many many hours of grief.