我发现有时候在尝试使用Keychain
API获取以前成功存储的安全项目时会出现错误。当我在我的设备中运行的应用程序处于后台状态并锁定屏幕时,我找到了它。设备没有锁定代码集,这就是我正在调用的功能:
+ (NSString *)findValueForKey:(NSString *)keyStr
{
NSString *valueStr = @"";
if ((keyStr != nil) && (![keyStr isEqualToString:@""])) {
NSString *service = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *query = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService : service,
(__bridge id)kSecAttrAccount : keyStr,
(__bridge id)kSecReturnData : (__bridge id)kCFBooleanTrue};
CFDataRef cfValue = NULL;
OSStatus results = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&cfValue);
if ([self checkIfNoError:results]) {
valueStr = [[NSString alloc] initWithData:(__bridge_transfer NSData *)cfValue encoding:NSUTF8StringEncoding];
}
else {
NSLog(@"%@", [self getErrorMessageForStatus:results]);
}
}
return valueStr;
}
并通过调用此方法存储该项:
+ (BOOL)storeInKeychainWithKey:(NSString *)keyStr withValueStr:(NSString *)valueStr
{
if ((keyStr != nil) && (![keyStr isEqualToString:@""]) &&
(valueStr != nil) && (![valueStr isEqualToString:@""])) {
NSData *valueData = [valueStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *service = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *secItem = @{(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService : service,
(__bridge id)kSecAttrAccount : keyStr,
(__bridge id)kSecValueData : valueData};
CFTypeRef result = NULL;
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)secItem, &result);
NSLog(@"%@", [self getErrorMessageForStatus:status]);
return [self checkIfItem:status];
}
else {
return NO;
}
}
我认为钥匙串项目总是可以在iOS中访问...这post似乎是类似的东西,但我不确定它是否已被弃用,我应该如何解决这个问题...
提前致谢
答案 0 :(得分:0)
我们有同样的问题,@ AppsDev,你提到的帖子是准确的。我们通过将钥匙串作为我们需要的东西的最后手段来解决它,即使我们卸载/重新安装应用程序。
我们现在循环回应用默认设置(在Swift 3中为UserDefaults.standard),以便在安装生命周期未到达“已卸载”阶段时保持该信息的便利。
如果卸载,下次安装时我们会转到钥匙串(根据定义,刚安装的应用程序不在后台,因此不会失败)。检索到数据后,我们会刷新应用程序默认值,然后我们只使用应用程序默认值。