Xcode 8 でキーチェーンを共有するには。
1) Capabilities の App ターゲットで、「キーチェーン共有」を見つけてオンにし、キーチェーン グループ キー (com.myappdomain.myappname のような逆ドメイン スタイルの文字列) を追加します。
2) 拡張ターゲットについてもまったく同じことを行います。キーチェーン グループ キーが、アプリと拡張機能の両方で同じであることを確認してください。
通常の方法でキーチェーンからデータを追加および取得します。コードに特別な変更は必要ありません。たとえば、メイン アプリのキーチェーンにデータを入れる方法を次に示します (少し古風ですが、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
}
}
正しいレコードを識別するために、「login」と「domain」を拡張機能に渡す必要があることに注意してください。これは NSUserDefaults を介して行うことができます。これを行う方法については、この回答を参照してください。