NSUserDefaults losing its keys & values when phone is rebooted but not unlocked

前端 未结 4 1007
感动是毒
感动是毒 2020-12-04 07:02

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 i

4条回答
  •  攒了一身酷
    2020-12-04 07:38

    We also experienced this problem when using significant location change, on devices with pass code enabled. The app launches on BG before the user even unlock the pass code, and UserDefaults has nothing.

    I think it is better to terminate the app before the synchronize occurs, because the reasons below:

    • UserDefaults' synchronize should not be executed once after UserDefaults cleared by this bug.
    • we can't strictly control the call of synchronize because we use many 3rd party libraries.
    • the app will not do any good if UserDefaults can't be loaded (even before the user passes pass code lock).

    So here's our (a bit weird) workaround. The app kills itself immediately when the situation (app state = BG, UserDefaults is cleared, iOS >= 7) detected.

    It should not violate UX standard, because terminating app on background will not be even noticed by the user. (And also it occurs before the user even passes the pass code validation)

    #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
    
    + (void)crashIfUserDefaultsIsInBadState
    {
        if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")
            && [UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
            if ([[NSUserDefaults standardUserDefaults] objectForKey:@"firstBootDate"]) {
                NSLog(@"------- UserDefaults is healthy now.");
            } else {
                NSLog(@"----< WARNING >--- this app will terminate itself now, because UserDefaults is in bad state and not recoverable.");
                exit(0);
            }
        }
        [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"firstBootDate"];
    }
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        [self.class crashIfUserDefaultsIsInBadState]; // need to put this on the FIRST LINE of didFinishLaunchingWithOptions
    
        ....
    }
    

提交回复
热议问题