我刚刚在我的应用程序中发现了一个有趣的问题。在应用程序中,我将用户的用户名和密码保存到钥匙串(keychain)中。
keychainWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyLoginPassword" accessGroup:nil];
[keychainWrapper setObject:usernameField.text forKey:(id)kSecAttrAccount];
[keychainWrapper setObject:passwordField.text forKey:(id)kSecValueData];
当这段代码在 Debug 中运行时,它似乎工作得很好。它每次都会更新,以后我可以从钥匙串(keychain)中检索项目。但是,当它在 Distribution 中运行时,钥匙串(keychain)永远不会更新。我已经验证是的,这些代码行在两个构建中都被命中了。我正在使用带有 iOS5 SDK 的 Xcode 4.2,并在安装了 iOS5 的 iPad 2 上运行该应用程序。
最佳答案
我也遇到了这个问题,我花了很长时间才弄明白
有一个版本的“KeychainWrapper”在 NSAssert 中有它的 SecItemUpdate(除其他外)。
无论是谁做的都是白痴!在为发布/分发构建时,每个 NSAssert 都被取消,这意味着代码甚至无法运行。
例如:
NSAssert(SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck), @"Couldn't update the Keychain Item." );
需要成为
OSStatus status = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck);
NSAssert(status == noErr, @"Couldn't update the Keychain Item." );
注意实际的 SecItemUpdate 是如何移到 NSAssert 之外的,而是检查结果
重要说明: 尝试更新 kSecValueData 的值,而不指定 kSecAttrAccount 的值,也会导致断言失败。因此,如果您打算存储单个字符串的敏感数据(例如信用卡号列表),请务必在 kSecAttrAccount 属性中存储一些“帐户名”文本,如下所示:
static NSString* kCardListXML = @"cardListXML";
static NSString* cardListAccountName = @"cardListAccount";
-(void)setCardListXML:(NSString*)xml {
KeychainItemWrapper* wrapper =
[[KeychainItemWrapper alloc] initWithIdentifier:kCardListXML accessGroup:nil];
[wrapper setObject:cardListAccountName forKey:(id)CFBridgingRelease(kSecAttrAccount)];
[wrapper setObject:xml forKey:(id)CFBridgingRelease(kSecValueData)];
}
-(NSString*)getCardListXML {
KeychainItemWrapper* wrapper =
[[KeychainItemWrapper alloc] initWithIdentifier:kCardListXML accessGroup:nil];
[wrapper setObject:cardListAccountName forKey:(id)CFBridgingRelease(kSecAttrAccount)];
return [wrapper objectForKey:CFBridgingRelease(kSecValueData)];
}
关于iOS KeychainItemWrapper 未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8054285/