2015-11-17 64 views
1

我試圖使用鑰匙串服務來保存一個值,即使用戶重新安裝應用程序,該值仍會存在。因此,我使用SecItemCopyMatching檢查項目是否存在,它首次返回errSecItemNotFound,並使用SecItemAdd添加新項目,該項目返回errSecSuccess,但_attrs的值爲nil。另外,當第二次調用代碼時,SecItemCopyMatching仍然返回errSecItemNotFound,就好像SecItemAdd未被調用。那麼這可能與什麼有關?SecItemCopyMatching不斷返回errSecItemNotFound

CFMutableDictionaryRef _attrs = nil; 
    NSString* key = @"<unique key>"; 
    NSMutableDictionary* query = [NSMutableDictionary dictionary]; 
    query[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword; 
    query[(__bridge id)kSecAttrLabel] = key; 
    query[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; 
    query[(__bridge id)kSecReturnAttributes] = (__bridge id)kCFBooleanTrue; 

    OSStatus err = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef*)&_attrs); 

    if (err == errSecSuccess) { 
     return YES; 
    } 
    NSString* str = @"<some data>"; 
    if (err == errSecItemNotFound) { 
     query[(__bridge id)kSecValueData] = NSData_from_string(string_from_NSString(str)); 
     query[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAlways; 
     err = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef*)&_attrs); 
     assert(err == errSecSuccess); 
    } 

回答

1

query你的電話到SecItemAdd重新使用,並且kSecMatchLimit價值存在於字典此功能打破它。在致電SecItemAdd之前,您應該刪除此密鑰。

還值得注意的是,[str dataUsingEncoding:NSUTF8StringEncoding]可能是比NSData_from_string(string_from_NSString(str))更好的選擇,具體取決於你在做什麼。

+0

它似乎可行,但我不明白爲什麼。 'kSecMatch'鍵不適用於'SecItemAdd',或者我會使用'kSecMatchAll'來傳遞?我不記得在閱讀文檔時遇到這個問題...... – tonso

+0

「SecItemCopyMatching」文檔表明您可以將文檔(如'kSecMatchLimit')的「搜索常量」部分中的項目添加到查詢中。 'SecItemAdd'文件沒有指出這一點,看起來查詢中存在的這些常量會打斷調用(或者至少使它不像你所期望的那樣)。 –

+0

明白了,謝謝。 – tonso