import Foundation import Security protocol KeychainStoreProtocol { func save(_ value: String, for key: String) -> Bool func read(for key: String) -> String? func delete(for key: String) -> Bool } final class KeychainStore: KeychainStoreProtocol { func save(_ value: String, for key: String) -> Bool { let data = Data(value.utf8) let query: [CFString: Any] = [ kSecClass: kSecClassGenericPassword, kSecAttrAccount: key, kSecValueData: data ] SecItemDelete(query as CFDictionary) return SecItemAdd(query as CFDictionary, nil) == errSecSuccess } func read(for key: String) -> String? { let query: [CFString: Any] = [ kSecClass: kSecClassGenericPassword, kSecAttrAccount: key, kSecReturnData: true, kSecMatchLimit: kSecMatchLimitOne ] var item: CFTypeRef? guard SecItemCopyMatching(query as CFDictionary, &item) == errSecSuccess, let data = item as? Data else { return nil } return String(data: data, encoding: .utf8) } func delete(for key: String) -> Bool { let query: [CFString: Any] = [ kSecClass: kSecClassGenericPassword, kSecAttrAccount: key ] return SecItemDelete(query as CFDictionary) == errSecSuccess } }