我刚发现我的应用程序存在一个有趣的问题。在应用程序中,我将用户的用户名和密码保存到钥匙串。
keychainWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyLoginPassword" accessGroup:nil];
[keychainWrapper setObject:usernameField.text forKey:(id)kSecAttrAccount];
[keychainWrapper setObject:passwordField.text forKey:(id)kSecValueData];
当在Debug中运行此代码时,它似乎工作得很好。它每次都会更新,之后我可以从钥匙串中检索这些项目。当它在Distribution中运行时,钥匙串永远不会更新。我已经验证了这两行代码都会遇到这些代码行。我正在使用Xcode 4.2和iOS5 SDK,并在安装了iOS5的iPad 2上运行应用程序。
答案 0 :(得分:17)
我也有这个问题,我花了很长时间才弄清楚
有一个版本的“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)];
}
答案 1 :(得分:16)
当你加入
时keychainWrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"MyLoginPassword" accessGroup:nil];
[keychainWrapper setObject:usernameField.text forKey:(id)kSecAttrAccount];
[keychainWrapper setObject:passwordField.text forKey:(id)kSecValueData];
您还必须包含
[keychainWrapper setObject:@"Myappstring" forKey: (id)kSecAttrService];
或者我收到“SIGABRT”错误。 (Myappstring)是一个定义应用程序的字符串。
也许我错过了一些东西,这应该至少完成一次。