有没有办法在单个事务中以原子方式将多个值写入钥匙串,以保证它们全部写入成功,或者在发生任何失败时,都不会写入?
我们的应用程序中有一个错误,我们依次写入 4 个值(作为迁移的一部分),但日志报告某些用户仅存在其中 2 或 3 个值,大概是因为应用程序在写入过程中崩溃了.
SecItemAdd
文档 建议以下内容...
要一次向钥匙串添加多个项目,请使用属性字典中的
键,并使用一组字典(每个字典对应于其中一个项目)作为其值。仅支持非密码项目。kSecUseItemList
然而,
kSecUseItemList
似乎仅适用于 macOS,在 iOS 上不可用。
kSecUseItemList 是 KeyChain Service API 中使用的密钥,允许您指定要在某些场景中使用的“现有钥匙串项目引用”数组。 我们通常不会将其写入钥匙串。相反,我们使用它来帮助对钥匙串中已存在的钥匙串项目执行批处理操作。
如果您想添加新的钥匙串项目,您可以使用 SecItemAdd。
...
import Security
...
func addItemToKeyChain() {
let account = "[email protected]"
let password = "useSecretPasswordOnly"
// Create a dictionary with the item you want to add to the keychain
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecValueData as String: password.data(using: .utf8)!]
// Atempt to add the item to the KeyChain
let status = SecItemAdd(query as CFDictionary, nil)
if status == errSecSuccess {
print("Success")
} else {
print("Error : \(status)")
}
}
...
钥匙串项:查询字典包含定义钥匙串项(类、帐户和数据)所需的属性。 SecItemAdd:此函数添加钥匙串项目。
这里是一个批量操作的场景。 如果您想执行批量操作,例如一次删除或更新多个项目,您可以使用 kSecUseItemList 来引用现有项目。
...
import Security
...
function deleteMultipleKeyChainItems(){
let keychainItems: [CFTypeRef] = [
// Keychain items to be deleted
["class": kSecClassGenericPassword, "account": "account1"] as CFDictionary,
["class": kSecClassGenericPassword, "account": "account2"] as CFDictionary
]
// Construct query to delete items from the Keychain
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
kSecUseItemList as String: keychainItems]
// Attempt to delete the items from Keychain
let status = SecItemDelete(query as CFDictionary)
if status == errSecSuccess {
print("Success")
} else {
print("Error : \(status)")
}
}
...