UserDefaults value is sometimes returning incorrect value

We use UserDefaults in our app to identify if we already showed a particular UI to the user (so that it will not be shown to the user again). Our logic goes something like:

if !UserDefaults.standard.alreadyShownToUser {
    showUI()
    UserDefaults.standard.alreadyShownToUser = true
}

But there are users who see this particular screen again when they open the app. The screen does not show up for a few days, and then suddenly, it shows up again.

Our theory is that this might have something to do with iOS Prewarming. So we updated our code to add another check:

if UIApplication.shared.isProtectedDataAvailable && !UserDefaults.standard.alreadyShownToUser

However, it does NOT seem to work / mitigate the issue at all. We also added logs to check the value of UIApplication.shared.isProtectedDataAvailable and the value of the UserDefaults variable.

We expected that if: UIApplication.shared.isProtectedDataAvailable is false, then the UserDefaults value should also be false.

But in our logs, we can see that UIApplication.shared.isProtectedDataAvailable is false, but UserDefaults still returned true.

Which led me to think that UserDefaults is not affected by Prewarming. Now, I'm back from the start.

What's causing our UserDefaults to have different value? We also do not have anywhere else in the app that sets the value of UserDefaults.standard.alreadyShownToUser to false. The only time it should have that value is when the user installs the app for the first time.

I appreciate any help that can lead me to fix this issue. Thank you!

Replies

if let myTest = UserDefaults.standard.value(forKey: "alreadyShownToUser") as? Bool{

}
UserDefaults.standard.set(isProtected, forKey: "alreadyShownToUser")

But instead of the string, I use an enum to prevent typing errors and make it easy to remember.

there are users who see this particular screen again when they open the app.

Are they hallucinating?

Did they see it on another device?

Have they deleted and re-installed the app?

Did they see a similar screen in a different app with a similar name to yours?

Anyway, why are you using NSUserDefaults for this? Can't you store this flag in the filesystem, somewhere that you have control over it, without the layer of opaque Apple magic that NSUserDefaults adds?

Are you sure you save UserDefaults in all cases after this :

if !UserDefaults.standard.alreadyShownToUser {
    showUI()
    UserDefaults.standard.alreadyShownToUser = true
}

If user quits immediately after this, it may not be saved. And next time app is opened, UserDefaults.standard.alreadyShownToUser is still false.