UserDefaults not persisting data

Hi,
We are experiencing what seems to be a fairly widespread, but intermittent issue with one of our apps. Anecdotally I have only seen this in person on iOS 14.4 devices, but I suspect based on our analytics that it is also happening on other versions too.

Basically the UserDefaults seems to be reverting to its initial defaults setting for some users which is causing our pre installed flag to revert to nil. This flag is purely used as a "firstLaunch" detection to determine if the app should clear its cache and show the first time login flow. Therefore this property not saving is having the effect of logging a user out every time they close the app.

I've attached the AppDelegate didFinishLaunching code below, only change is I have redacted our company name and replaced it with MyApp The important part which is intermittently failing is the if statement
if !UserDefaults.standard.bool(forKey: "pre installed") || UserDefaults.standard.bool(forKey: "MyAppSettingsResetState")

For clarity, once an app gets into this state it no longer seems to be able to save to the UserDefaults, so it will always log itself out on next launch. It also seems to fix itself if I delete the app from the phone and reinstall, then the UserDefaults return to working as expected.

Code Block    
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
     
    SentrySDK.start { options in
      options.dsn = Constants.sentryID
      options.environment = Constants.sentryEnvName
      options.debug = Constants.env == Env.Production ? false : true
    }
     
    _ = MyAppSDK.sharedSDK
    MyAppSDK.sharedSDK.configure(baseURL: Constants.baseURL, gatewayBaseURL: Constants.gatewayBaseURL)
    MyAppSDK.sharedSDK.errorLogging = SentryHelper()
     
    AWSMobileClient.default().initialize { (userState, error) in
      if let err = error {
        print("error: \(err)")
      }
      if let userState = userState {
        print("UserState: \(userState.rawValue)")
      }
    }
     
    if !UserDefaults.standard.bool(forKey: "pre installed") || UserDefaults.standard.bool(forKey: "MyAppSettingsResetState") {
      MyAppSDK.sharedSDK.logout()
      MyAppSDK.sharedSDK.updateAPNToken(token: "")
      UserDefaults.standard.set(true, forKey: "pre installed")
      UserDefaults.standard.set(false, forKey: "MyAppSDKSettingsResetState")
    }
     
    UNUserNotificationCenter.current().getNotificationSettings { (settings) in
      if settings.authorizationStatus == .authorized {
        DispatchQueue.main.async {
          UIApplication.shared.registerForRemoteNotifications()
        }
      }
    }
     
    UNUserNotificationCenter.current().delegate = self
    settingsInfo()
    return true
  }


If anyone has experienced this before and knows how to fix it or what might be causing some users apps to get into this state. I would love to hear from you, I've been going round in circles with this for several days now.
Answered by jason_tga in 663463022
Sorry, I guess context would have been applicable "MyAppSettingsResetState" is a toggle on the settings page of our app so it would be true if a user had gone into the settings page and logged out.

I've since discovered the cause of my issue here and its actually related to that setting.

Basically it was just a programming error on my part for an edge case.

It was happening if the user had given notification permissions, logged out then opened the app again. registerForRemoteNotifications() was still being called and in the didRegisterForRemoteNotificationsWithDeviceToken we send the APN token to our server which obviously fails because the user had logged out and no longer has a valid session. Then upon the Auth error our SDK was clearing its cache and clearing all the UserDefaults.
I do not see how UserDefaults.standard.bool(forKey: "MyAppSettingsResetState") could ever be true in your code.
When app launches first time, key does not exist, hence it is false.
But as pre installed is false also, || condition is met and "MyAppSettingsResetState" is set false?
Accepted Answer
Sorry, I guess context would have been applicable "MyAppSettingsResetState" is a toggle on the settings page of our app so it would be true if a user had gone into the settings page and logged out.

I've since discovered the cause of my issue here and its actually related to that setting.

Basically it was just a programming error on my part for an edge case.

It was happening if the user had given notification permissions, logged out then opened the app again. registerForRemoteNotifications() was still being called and in the didRegisterForRemoteNotificationsWithDeviceToken we send the APN token to our server which obviously fails because the user had logged out and no longer has a valid session. Then upon the Auth error our SDK was clearing its cache and clearing all the UserDefaults.
UserDefaults not persisting data
 
 
Q