Reputation: 1200
I'm getting an error saving an encoded value to keychain at the point of SecItemAdd
. I'm fairly new to working with Keychain and not sure how to return the error to see what I'm doing incorrectly.
let encoder = JSONEncoder()
func initiateLogin(forceReconnect: Bool = false, completion: @escaping (Bool)->Void) {
Task {
await loginUser(forceReconnect: forceReconnect, completion: { user in
if let encoded = try? self.encoder.encode(user) {
// MARK: - keychain
let attributes: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "johnDoe",
kSecValueData as String: encoded,
]
if SecItemAdd(attributes as CFDictionary, nil) == noErr {
print("\(#function) 😀 user saved successfully in keychain")
} else {
print("\(#function) ⚠️ something went wrong")
}
self.initClient(withCredentials: user)
completion(true)
}
})
}
}
Upvotes: 0
Views: 1152
Reputation: 13995
You didn't specify which error you are getting (it should be a return value of SecItemAdd
), but the most common mistake is this: as documentation states:
The operation might fail, for example, if an item with the given attributes already exists.
In other words: your code will only work once for each unique kSecAttrAccount
.
Instead, you need to check if an item already exists, and if yes, update it (or delete the previous one and create a new one).
How to update the items or delete them is explained here.
Side note: it's also a good idea to put keychain management into a separate class (a wrapper), which you can call from anywhere in your code to save / load data from keychain. Here's a good tutorial on how to create such wrapper.
Upvotes: 4