成功将String值存入keychain,但总是读取失败

Successfully stored String value to keychain, but always failed to read it out

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

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

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([=10=]))
    }

    // 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()

我得到 hasStoredtrue,但 readVal 总是 nil。我调查了我的函数,我发现我总是 得到错误 -50 作为 reader 函数 中的状态代码(请参阅我在函数中的评论)。

为什么?为什么我无法读取存储在钥匙串中的值(我不确定它是否真的存储了但我确实得到 status == noErr always retuns true in storeString(value:) function)

您的代码中有错别字:

query[kSecMatchLimit as String] = kSecMatchLimit
//                                ^~~~~~~~~~~~~~

kSecMatchLimit 是键,不是有效值。预期值应为 CFNumberkSecMatchLimitOnekSecMatchLimitAll。如果您希望退回单个项目,请使用 kSecMatchLimitOne。另见 Search Attribute Keys and Values