1

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

- (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即可将密码添加到钥匙串中。我从这里使用 KeychainItemWrapper将密码 NSString 转换为 NSData 但不会再次将其转换回来,这就是我这样做的原因。

编辑 2 ----

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

4

2 回答 2

1

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

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

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

也看看这些:

iOS KeyChain 未从后台检索值

iOS Keychain 偶尔会返回空字符串

Apple 技术讲座视频

于 2014-03-11T17:58:13.003 回答
0

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

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

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

于 2014-03-11T18:11:02.427 回答