SecItemCopyMatching 不断返回 errSecItemNotFound

SecItemCopyMatching keeps returning errSecItemNotFound

我正在尝试使用钥匙串服务来保存一个值,即使用户重新安装该应用程序,该值也会持续存在。因此,我第一次使用 SecItemCopyMatching 检查项目是否存在,其中 returns errSecItemNotFound 并使用 SecItemAdd 添加新项目,其中 returns errSecSuccess,但 _attrs 的值为 nil。另外,当第二次调用代码时,SecItemCopyMatching 仍然是 returns errSecItemNotFound,就好像 SecItemAdd 没有被调用一样。那么这可能与什么有关?

    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);
    }

您正在重新使用 query 来调用 SecItemAdd,并且此函数的字典中存在的 kSecMatchLimit 值正在破坏它。您应该在调用 SecItemAdd.

之前删除此密钥

还值得注意的是,[str dataUsingEncoding:NSUTF8StringEncoding] 可能比 NSData_from_string(string_from_NSString(str)) 更好,具体取决于您在做什么。