使钥匙串在 Xcode 8 中共享。
1) 在 Capabilities 的 App 目标中找到并打开“Keychain Sharing”,添加一个 Keychain Group 密钥(一个反向域样式的字符串,如 com.myappdomain.myappname)
2)对扩展目标执行完全相同的操作。确保应用程序和扩展程序的钥匙串组密钥相同。
以您通常的方式从 Keychain 添加和检索数据,无需对代码进行特殊更改。例如,这是我在主应用程序中将数据放入 Keychain 的方式(有点过时,但在 Swift 3 中仍然有效):
let login = loginString
let domain = domainString
let passwordData: Data = passwordString.data(using: String.Encoding.utf8, allowLossyConversion: false)!
let keychainQuery: [NSString: NSObject] = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: login as NSObject, // login and domain strings help identify
kSecAttrService: domain as NSObject, // the required record in the Keychain
kSecValueData: passwordData as NSObject]
SecItemDelete(keychainQuery as CFDictionary) //Deletes the item just in case it already exists
let keychainSaveStatus: OSStatus = SecItemAdd(keychainQuery as CFDictionary, nil)
然后在扩展中检索它:
let keychainQuery: [NSString: NSObject] = [
kSecClass: kSecClassGenericPassword,
kSecAttrAccount: login as NSObject,
kSecAttrService: domain as NSObject,
kSecReturnData: kCFBooleanTrue,
kSecMatchLimit: kSecMatchLimitOne]
var rawResult: AnyObject?
let keychain_get_status: OSStatus = SecItemCopyMatching(keychainQuery as CFDictionary, &rawResult)
if (keychain_get_status == errSecSuccess) {
if let retrievedData = rawResult as? Data,
let password = String(data: retrievedData, encoding: String.Encoding.utf8) {
// "password" contains the password string now
}
}
请注意,您仍然需要将“登录”和“域”传递给扩展程序,以便识别正确的记录。这可以通过 NSUserDefaults 来完成。请参阅此答案以了解如何执行此操作。