重新启动手机但未解锁时,NSUserDefaults会丢失其键和值

2020/12/16 12:31 · ios ·  · 0评论

我们的iPhone应用程序当前遇到以下奇怪问题。如标题所述,NSUserDefaults当手机重新启动但未解锁时,我们的自定义键和值将丢失,这是在非常特定的情况下发生的。

内容:

  • 我们正在NSUserDefaults应用中使用来存储用户数据(例如用户名)。

  • 我们的应用在后台模式下启用了位置信息。

  • 我们仅在通过空中分发或通过Testflight时遇到此问题。如果我使用Xcode将.ipa(通过空中分发的相同内容)拖放到手机中,则不会遇到此问题。

情况:用户安装应用程序,登录并NSUserDefaults成功将用户名存储在用户名上然后,用户关闭设备并将其重新打开,并让手机在解锁屏幕之前先坐一会儿。

问题:如果在那个时候触发了重大的位置更改,则该应用程序将在后台运行,但该应用程序NSUserDefaults为空(仅苹果提供了一些键,但没有自定义键)。然后,NSUserDefaults无论您做什么,此密钥都永远不会恢复(例如,如果您解锁手机并打开应用程序,您将仍然看到密钥丢失)。

任何帮助或想法将不胜感激:)

我有一个非常相似的问题。后台应用程序。使用其他占用大量内存的应用程序,直到从内存中删除我的应用程序为止。(如果插入了设备并运行了xcode,则可以观察到此事件。Xcode会告诉您“应用程序由于内存不足而终止。)。如果您的应用程序注册了后台获取事件,它将在此处唤醒指向并重新启动,但进入后台。这时,如果您的设备被锁定,则NSUserDefaults将为null。

经过数天的调试,我发现并不是NSUserDefaults被损坏或被淘汰,而是因为设备锁定导致应用程序无法访问它。如果您手动尝试通过xcode Organizer下载应用程序内容,则实际上可以观察到这种现象,如果设备保持锁定状态,则会注意到不存在用于存储NSUserDefaults设置的plist。

好的,因此如果在设备锁定时将应用程序启动到后台,则NSUserDefaults将不可访问。没什么大不了,但是最糟糕的部分是,一旦应用程序启动到后台,它就会保留在内存中。此时,如果用户随后解锁设备并将应用程序启动到前台,则您在NSUserDefaults内仍然没有任何内容。这是因为一旦应用程序将NSUserDefaults加载到内存中(该属性为null),一旦设备解锁,就不知道要重新加载它。在这种情况下,同步不执行任何操作。我发现解决了我的问题的是打电话给

[NSUserDefaults resetStandardUserDefaults]里面的applicationProtectedDataDidBecomeAvailable方法。

希望这对某人有帮助。这些信息可能使我免于许多小时的痛苦。

一段时间后,Apple将此视为官方错误。因此,在解决之前,我们只剩下不同的解决方法:

  1. 如果在解锁手机之前执行时需要数据,请使用以下选项之一并设置NSPersistentStoreFileProtectionKey = NSFileProtectionNone选项:

    • 使用核心数据保存数据。(如果您需要访问DB在后台的时候,手机还没有解锁,你不必在这敏感信息,您可以添加到阵列选项以下选项:NSPersistentStoreFileProtectionKey = NSFileProtectionNone
    • 使用钥匙串。
    • 使用.plist文件。
    • 使用自定义文件:(例如:具有特定格式的.txt)。
    • 您可能会觉得适合的其他任何方式存储数据。

    选择你的;)

  2. 如果在解锁手机之前不需要或不关心数据,则可以使用以下方法(感谢@maxf):

    注册到applicationProtectedDataDidBecomeAvailable:通知并在回调中执行以下代码行[NSUserDefaults resetStandardUserDefaults]

    这将使您NSUserDefault在电话被授予访问受保护数据的权限后立即重新加载,从而帮助您完全避免此问题。

谢谢大家的帮助!

在启用密码的设备上使用重大位置更改时,我们也遇到了此问题。该应用程序在用户甚至解锁密码之前就已在BG上启动,而UserDefaults则一无所有。

我认为最好在同步发生之前终止应用程序,因为以下原因:

  • 此错误清除UserDefaults后,不应执行一次UserDefaults的同步。
  • 由于我们使用了许多第三方库,因此我们不能严格控制同步的调用。
  • 如果无法加载UserDefaults(即使在用户通过密码锁定之前),该应用程序也将无济于事。

所以这是我们的(有点奇怪)解决方法。检测到情况(应用程序状态= BG,清除了UserDefaults,iOS> = 7)后,应用程序会立即杀死自己。

它不应该违反UX标准,因为在后台终止应用程序甚至不会被用户注意到。(这也发生在用户甚至通过密码验证之前)

#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

    ....
}

自IOS 7.0起,这仍然是IOS 9.0上的行为。

我怀疑Apple不会更改此设置,因为这是[NSUserDefaults standardUserDefaults]加载的.plist受NSFileProtectionCompleteUntilFirstUserAuthentication保护的事实的结果。

另请参阅为什么IOS7电池没电后不读取NSUserDefaults

本文地址:http://ios.askforanswer.com/zhongxinqidongshoujidanweijiesuoshinsuserdefaultshuidiushiqijianhezhi.html
文章标签: ,   ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!