我正在尝试使用钥匙串服务来保存一个值,即使用户重新安装该应用程序,该值也将持续存在。因此,我使用SecItemCopyMatching检查项目是否存在,该项目第一次返回errSecItemNotFound,并使用SecItemAdd添加一个新项目,该项目返回errSecSuccess,但_attrs的值为nil。同样,当第二次调用该代码时,SecItemCopyMatching仍然返回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))可能是更好的选择。

10-08 07:30