我有以下代码在钥匙链中创建一个钥匙链项目:
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject: (__bridge id) kSecClassGenericPassword forKey: (__bridge id) kSecClass];
[dict setObject: MYKEY forKey: (__bridge id) kSecAttrService];
[dict setObject: @"0" forKey: (__bridge id) kSecValueData];
SecItemAdd ((__bridge CFDictionaryRef) dict, NULL);
这很好用。如果我想更改此项,有人能给出SecItemUpdate的语法吗?
更新:包含以下内容:
NSMutableDictionary *query = [NSMutableDictionary dictionary];
NSMutableDictionary *attributesToUpdate = [NSMutableDictionary dictionary];
[query setObject: (__bridge id) kSecClassGenericPassword forKey: (__bridge id) kSecClass];
[query setObject: MYKEY forKey: (__bridge id) kSecAttrService];
[query setObject: (id) kCFBooleanTrue forKey: (__bridge id) kSecReturnData];
NSString *numberOfBalloonsString = [NSString stringWithFormat:@"%d", numberOfBalloonsUsed];
NSData *numberOfBalloonsData = [numberOfBalloonsString dataUsingEncoding:NSUTF8StringEncoding];
[attributesToUpdate setObject: numberOfBalloonsData forKey:(__bridge id)kSecValueData];
OSStatus error = SecItemUpdate ((__bridge CFDictionaryRef) query, (__bridge CFDictionaryRef) attributesToUpdate);
NSLog(@"Error #: %ld", error);
我得到错误代码-50=
传递给函数的一个或多个参数无效。
SecItemUpdate
的文档非常丰富。
SecItemUpdate
的query
参数记录为一个查询(在其他函数中使用)以及一个模糊的语句:"指定要更改其值的项"。这似乎意味着你必须在这个字典中包含你想要更改的现有属性值,但我不认为你这样做。我发现你可以使用相同的query
来获取你想要更新的项目的属性。
attributes
参数应该是添加了kSecValueData
键和值并更改了任何属性的SecItemCopyMatching
的结果。
一个迟来的答案,但仍然是一个答案:
我也一直在努力更新钥匙链中的项目,不过我的上下文有点不同。
发生了什么:
我可以成功地添加一个密钥链项目(使用SecItemAdd
),但在同一个项目上调用SecItemUpdate
失败,出现了臭名昭著的errSecParam -50
更糟糕的是;如果钥匙链项目已经存在(因此我立即调用了SecItemUpdate
),那么更新就顺利完成了
我完全不知道为什么会发生这种事。。。
我是如何修复的:
实际上很简单,我只是删除了"params",直到大坏的-50
得到满足。当我从kSecItemCopyMatching
检索到的字典中删除kSecClass
时,就发生了这种情况
这是我的代码:
// If the item already exists, we update it instead
if (SecItemCopyMatching((__bridge CFDictionaryRef)self.searchQueryDict, (CFTypeRef *)&foundItem) == errSecSuccess) {
NSMutableDictionary *updateDict = (__bridge NSMutableDictionary *)foundItem;
[updateDict addEntriesFromDictionary:dictToSave];
[updateDict removeObjectForKey:(__bridge id)kSecClass];
OSStatus updateSuccess = SecItemUpdate((__bridge CFDictionaryRef)self.updateQueryDict,
(__bridge CFDictionaryRef)updateDict);
NSAssert(updateSuccess == errSecSuccess, @"Couldn't save the dirty info to the keychain, might want to log the updateSuccess (%d)", updateSuccess);
}
作为参考,我使用了以下词典
包含self.searchQueryDict
:
(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword
(__bridge id)kSecAttrService : service
(__bridge id)kSecAttrGeneric : [identifier dataUsingEncoding:NSUTF8StringEncoding]
(__bridge id)kSecMatchLimit : (__bridge id)kSecMatchLimitOne
(__bridge id)kSecReturnAttributes : (__bridge id)kCFBooleanTrue
(__bridge id)kSecReturnData : (__bridge id)kCFBooleanTrue
包含self.updateQueryDict
:
(__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService : service,
(__bridge id)kSecAttrGeneric : [identifier dataUsingEncoding:NSUTF8StringEncoding]
dictToSave
应包含需要更改的值(格式正确)
删除kSecClass
为我解决了问题。