Skip to content

Instantly share code, notes, and snippets.

@joshavant
Created April 19, 2016 22:17
Show Gist options
  • Save joshavant/88c5ba4364d0d7161b63f30e953ec289 to your computer and use it in GitHub Desktop.
Save joshavant/88c5ba4364d0d7161b63f30e953ec289 to your computer and use it in GitHub Desktop.
Swifty Keychain Abstraction
protocol KeychainCoding {
init?(keychain: KeychainPersistable, identifier: KeychainPersistableIdentifer)
func encodeToKeychain(keychain: KeychainPersistable, identifier: KeychainPersistableIdentifer) throws
}
extension KeychainCoding where Self: NSCoding, Self: InstanceInitializable {
init?(keychain: KeychainPersistable, identifier: KeychainPersistableIdentifer) {
do {
if let data = try keychain.get(identifier) {
let unarchivedInstance = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! Self
self.init(instance: unarchivedInstance)
} else {
return nil
}
} catch {
return nil
}
}
func encodeToKeychain(keychain: KeychainPersistable, identifier: KeychainPersistableIdentifer) throws {
let data = NSKeyedArchiver.archivedDataWithRootObject(self)
try keychain.set(data, identifier: identifier)
}
}
import Foundation
import KeychainAccess
typealias KeychainPersistableIdentifer = String
protocol KeychainPersistable {
func set(value: NSData, identifier: KeychainPersistableIdentifer) throws
func get(identifier: KeychainPersistableIdentifer) throws -> NSData?
}
struct KeychainService: KeychainPersistable {
private let keychain: Keychain
init(accessGroupIdentifier identifier: String) {
keychain = Keychain(accessGroup: identifier)
}
// MARK: - KeychainPersistable
func set(value: NSData, identifier: KeychainPersistableIdentifer) throws {
try keychain.set(value, key: identifier)
}
func get(identifier: KeychainPersistableIdentifer) throws -> NSData? {
return try keychain.getData(identifier)
}
}
let keychain: KeychainPersistable = KeychainService(accessGroupIdentifier: "main")
let UserSessionCredentialsKeychainIdentifier = "CredentialsKeychainIdentifier"
// persist
let credentials = UserSessionCredentials(token: "123", userId: 123, expires: NSDate.distantFuture())
try! credentials.encodeToKeychain(keychain, identifier: UserSessionCredentialsKeychainIdentifier)
// fetch
let keychainCredentials: UserSessionCredentials? = UserSessionCredentials(keychain: keychain, identifier: UserSessionCredentialsKeychainIdentifier)
class UserSessionCredentials: NSObject, NSCoding, KeychainCoding, InstanceInitializable {
let token: String
let userId: Int
let expires: NSDate
private struct PropertyKey {
static let tokenKey = "token"
static let userIdKey = "userId"
static let expiresKey = "expires"
}
init(token: String, userId: Int, expires: NSDate) {
self.token = token
self.userId = userId
self.expires = expires
}
// MARK: - NSCoding
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(self.token, forKey: PropertyKey.tokenKey)
aCoder.encodeInteger(self.userId, forKey: PropertyKey.userIdKey)
aCoder.encodeObject(self.expires, forKey: PropertyKey.expiresKey)
}
required convenience init?(coder aDecoder: NSCoder) {
let token = aDecoder.decodeObjectForKey(PropertyKey.tokenKey) as! String
let userId = aDecoder.decodeIntegerForKey(PropertyKey.userIdKey)
let expires = aDecoder.decodeObjectForKey(PropertyKey.expiresKey) as! NSDate
self.init(token: token, userId: userId, expires: expires)
}
// MARK: - InstanceInitializable
required convenience init(instance: UserSessionCredentials) {
self.init(token: instance.token,
userId: instance.userId,
expires: instance.expires)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment