【问题标题】:NSString from NSData crash when run in background fetch在后台获取运行时来自 NSData 的 NSString 崩溃
【发布时间】:2014-03-11 17:47:33
【问题描述】:

我有这个方法可以检查我们是否在钥匙串中存储了用户名和密码:

- (BOOL)hasLoginDetails
{
    FLog
    NSString *username = [self.keychainItem objectForKey:(__bridge id)kSecAttrAccount];
    if (username == nil || [username isEqualToString:@""])
        return NO;

    NSData *passData = [self.keychainItem objectForKey:(__bridge id)kSecValueData];
    if (passData == nil || [passData length] == 0)
        return NO;

    NSString *password = [[NSString alloc] initWithData:passData encoding:NSUTF8StringEncoding];
    if (password == nil || [password isEqualToString:@""])
        return NO;

    return YES;
}

密码返回为NSData,因此需要转换为字符串。这在正常使用中工作得非常好,但是当它在后台使用application:performFetchWithCompletionHandler: 方法时,我有时会遇到指向这一行的崩溃:

NSString *password = [[NSString alloc] initWithData:passData encoding:NSUTF8StringEncoding];

崩溃日志抱怨

-[__NSCFString bytes]: unrecognized selector sent to instance 0x156104a0

我只在分发 AdHoc 构建后才看到这些崩溃。 我假设崩溃日志说 passData 变量此时实际上是一个字符串? 有什么想法吗?

谢谢

编辑----

密码被添加到钥匙串中,只需使用[self.keychainItem setObject:password forKey:(__bridge id)kSecValueData]; password 作为 NSString。我正在使用来自here 的 KeychainItemWrapper,它将密码 NSString 转换为 NSData 但不会再次将其转换回来,这就是我这样做的原因。

编辑 2 ----

在调试崩溃后,我检查了你的 passData 变量,实际上应该是 NSData 的 NSString,所以有时我得到 NSData,而且我时不时地得到 NSString。

【问题讨论】:

  • 你能发布完整的跟踪吗?请大意
  • 如何设置[self.keychainItem objectForKey:(__bridge id)kSecValueData]; 是在其中放置NSData 还是插入NSString
  • kSecValueData 的类型是什么?为什么你不能把它留为NSString
  • 我相信KeychainItemWrapper 将 NSString 转换为 NSData 以获得更高的安全性。这是为密码字段自动完成的。

标签: ios nsstring nsdata unrecognized-selector keychainitemwrapper


【解决方案1】:

根据您为钥匙串项目设置的数据保护选项,当手机被锁定时,钥匙串将无法访问,因此您会获得一些意外的值并因此崩溃。

这实际上是一个非常受欢迎的问题,以至于 Apple 在他们的技术谈话视频中专门解决了这个问题。

您能粘贴处理设置钥匙串项的代码吗?

还可以看看这些:

iOS KeyChain not retrieving values from background

iOS Keychain occasionally return empty string

Apple Tech Talk Video

【讨论】:

  • 如果这是问题,则崩溃不会出现在该行中,如果:if (passData == nil || [passData length] == 0) return 0 确保钥匙串正在返回某些内容,请记住这一点
  • 谢谢。我已经更新了问题。我有时可以让它在模拟器上崩溃,但不会太多。
  • 我刚刚在崩溃后检查了passData的变量内容,实际上应该是NSData的NSString,所以有时我得到数据,有时我得到一个字符串!
【解决方案2】:

寻找这个特定的错误我发现这个异常发生然后你尝试调用方法initWithData:encoding:传递NSString而不是NSData

无法识别的选择器发送到 NSKeyedUnarchiver 的实例:Source

请检查您的代码,当您保存密码时,是否将其保存为字符串?如果您这样做,您不必initWithData:encoding: 阅读,您可以或按原样阅读或NSString initWithString:

【讨论】:

  • 如果是这样的话,代码每次都会崩溃,而不仅仅是在后台。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多