Ios 已成功将字符串值存储到keychain,但始终无法读取

Ios 已成功将字符串值存储到keychain,但始终无法读取,ios,swift3,keychain,Ios,Swift3,Keychain,我正在用XCode8+Swift3开发一个iOS项目 我创建了以下两个函数来将字符串存储到keychain并从keychain读回: var query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrService as String: "my service", kSecAttrAccount as String: "my-key" ] func storeStrin

我正在用XCode8+Swift3开发一个iOS项目

我创建了以下两个函数来将字符串存储到keychain并从keychain读回:

var query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrService as String: "my service",
    kSecAttrAccount as String: "my-key"
]

func storeString(value: String) -> Bool {
    if let data = value.data(using: .utf8) {
        // delete data if exist
        SecItemDelete(query as CFDictionary)

        // add value to query
        query[kSecValueData as String] = data

        // add to keychain
        let status = SecItemAdd(query as CFDictionary, nil)

        return status == noErr
    }
    return false
}

func readString() -> String? {
    // update query
    query[kSecReturnData as String] = kCFBooleanTrue
    query[kSecMatchLimit as String] = kSecMatchLimit

    var result: AnyObject?
    // fetch items from keychain
    let status: OSStatus = withUnsafeMutablePointer(to: &result) {
        SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
    }

    // I always get error -50 here
    if status == noErr {
        if let resultData = result as? Data {
            if let strVal = String(data: resultData, encoding: .utf8) {
                return strVal
            }
        }
    }
    return nil

}
我调用以下函数:

boolean hasStored = storeString(value: "John")
let readVal = readString()
我得到的
hasStored
true
,但是
readVal
总是
nil
。我调查了我的函数,我发现我总是在reader函数中获取错误-50作为状态代码(参见我函数中的注释)


为什么??为什么我无法读取存储在keychain中的值(我不确定它是否真的存储了,但我确实得到了
状态==noErr
始终在
存储字符串(值:)
函数中重新运行
true

您的代码中有一个输入错误:

query[kSecMatchLimit作为字符串]=kSecMatchLimit
//                                ^~~~~~~~~~~~~~

kSecMatchLimit
是键,不是有效值。预期值应为
CFNumber
kSecMatchLimitOne
kSecMatchLimitAll
。如果您希望返回单个项目,请使用
kSecMatchLimitOne
。另请参见。

如果将
kSecMatchLimit
的值设置为
kSecMatchLimitOne
,会发生什么情况?@Max,请您回答,我会接受。更改为
kSecMatchLimitOne
后,它现在可以工作。如果您也能解释一下为什么/是什么让您认为
kSecMatchLimitOne
可以解决这个问题(以帮助其他人),那就太好了:)