Ios NSUserDefaults丢失了它的钥匙&;手机重新启动但未解锁时的值
我们的iPhone应用程序目前遇到以下奇怪的问题。正如标题所说,Ios NSUserDefaults丢失了它的钥匙&;手机重新启动但未解锁时的值,ios,background,nsuserdefaults,core-location,reboot,Ios,Background,Nsuserdefaults,Core Location,Reboot,我们的iPhone应用程序目前遇到以下奇怪的问题。正如标题所说,NSUserDefaults在手机重新启动但未解锁时会丢失我们的自定义密钥和值,这是在一个非常特定的场景中发生的 背景: 我们在应用程序中使用NSUserDefaults存储用户数据(例如用户名) 我们的应用程序在后台模式下启用了位置 我们只有在通过空中或试飞进行分发时才会遇到此问题。如果我使用Xcode将.ipa(与空中分发的相同)拖放到手机中,我不会遇到这个问题 情况:用户安装应用程序并登录,用户名成功存储在NSUserDe
NSUserDefaults
在手机重新启动但未解锁时会丢失我们的自定义密钥和值,这是在一个非常特定的场景中发生的
背景:
- 我们在应用程序中使用
存储用户数据(例如用户名)NSUserDefaults
- 我们的应用程序在后台模式下启用了位置
- 我们只有在通过空中或试飞进行分发时才会遇到此问题。如果我使用Xcode将.ipa(与空中分发的相同)拖放到手机中,我不会遇到这个问题
NSUserDefaults
上。然后,用户关闭设备并重新打开,让手机在解锁屏幕前等待一段时间
问题:如果在此期间触发了重大的位置更改,应用程序将在后台运行,但NSUserDefaults
为空(只有一些来自苹果的密钥,但没有我们的自定义密钥)。然后,无论您做什么,NSUserDefaults
都不会恢复此密钥(例如,如果您解锁手机并打开应用程序,您将看到密钥仍然丢失)
任何帮助或想法都将受到真诚的感谢:)过了一段时间,苹果公司意识到这是一个官方错误。因此,在问题解决之前,我们只剩下不同的解决办法:
NSPersistentStoreFileProtectionKey=NSFileProtectionNone
选项:
- 使用核心数据保存数据。(如果您需要在手机尚未解锁时在后台访问DB,并且其中没有可感知的信息,则可以向选项数组中添加以下选项:
)NSPersistentStoreFileProtectionKey=NSFileProtectionNone
- 使用钥匙链
- 使用.plist文件
- 使用定制文件:(例如:具有特定格式的.txt)
- 您可能会觉得适合存储数据的任何其他方式
applicationProtectedDataDidBecomeAvailable:
通知并在回调中执行以下代码行[NSUserDefaults resetStandardUserDefaults]
这将使您在手机获得访问受保护数据的权限后立即重新加载NSUserDefault
,帮助您完全避免此问题谢谢大家的帮助 我也遇到了类似的问题。应用程序的背景。使用其他内存密集型应用程序,直到我的应用程序从内存中被丢弃。(如果插入设备并运行构建的xcode,则可以观察此事件。xcode将告诉您“由于内存压力,应用程序已终止”)。从这里开始,如果您的应用程序注册了后台获取事件,它将在某个点唤醒并重新启动,但会进入后台。此时,如果您的设备被锁定,则NSUserDefaults将为空 在调试这个案例几天后,我意识到不是NSUserDefaults被破坏或禁用,而是由于设备锁定,应用程序无法访问它。如果您手动尝试通过xcode organizer下载应用程序内容,您会注意到存储NS的plist如果设备保持锁定状态,则不存在UserDefaults设置 好的,如果在设备锁定时将应用程序启动到后台,则无法访问NSUserDefaults。这没什么大不了的,但最糟糕的是,一旦将应用程序启动到后台,它将保留在内存中。此时,如果用户解锁设备并将应用程序启动到前台,您仍然无法访问在NSUserDefaults中有任何内容。这是因为一旦应用程序将NSUserDefaults加载到内存中(该内存为null),它就不知道在设备解锁后重新加载它。在这种情况下,同步不起任何作用。我发现解决问题的方法是调用
[NSUserDefaults resetStandardUserDefaults]
在应用程序保护数据变得可用的方法中
希望这对某人有所帮助。此信息可能会让我省下许多小时的痛苦。在启用密码的设备上使用重大位置更改时,我们也遇到了此问题。在用户解锁密码之前,应用程序在BG上启动,而UserDefault没有任何内容
我认为最好在同步发生之前终止应用程序,原因如下:
- 此错误清除UserDefaults后,不应执行UserDefaults的同步
- 我们无法严格控制同步调用,因为我们使用了许多第三方库
- 如果无法加载UserDefaults(即使在用户通过密码锁之前),应用程序也不会有任何好处
下面是我们(有点奇怪)的解决方法。当检测到情况(app state=BG,UserDefaults被清除,iOS>=7)时,应用程序会立即自杀
它不应该违反UX标准,因为在后台终止应用程序甚至不会被用户注意到。(而且它发生在用户通过密码验证之前)
#定义系统版本(大于)或等于(v)([[UIDevice currentDevice]systemVersion]比较:v选项:NSNumericSearch]!=传感器解除搜索)
+(无效)crashIfUserDefaultsIsInBadState
{
如果(系统版本)大于
#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
....
}