Skip to content

Instantly share code, notes, and snippets.

@frzi
Last active November 3, 2021 16:32
Show Gist options
  • Save frzi/df82c0fe34c9e0116c70e3a49ecffddf to your computer and use it in GitHub Desktop.
Save frzi/df82c0fe34c9e0116c70e3a49ecffddf to your computer and use it in GitHub Desktop.
/**
* Keychain.swift
* Created by frzi (github.com/frzi)
*/
import Foundation
import Security
class Keychain {
fileprivate class func getKeychainQuery(_ key: String) -> NSMutableDictionary {
return [
kSecClass: kSecClassGenericPassword,
kSecAttrService: "myapp_identifier",
kSecAttrAccount: key,
]
}
@discardableResult
class func set(_ value: Data, forKey key: String) -> Bool {
let query = getKeychainQuery(key)
query[kSecValueData] = value
return SecItemAdd(query, nil) == noErr
}
@discardableResult
class func delete(_ key: String) -> Bool {
let query = getKeychainQuery(key)
return SecItemDelete(query) == noErr
}
class func get(_ key: String) -> Data? {
let query = getKeychainQuery(key)
var result: AnyObject?
query[kSecReturnData] = true
query[kSecMatchLimit] = kSecMatchLimitOne
if SecItemCopyMatching(query, &result) == noErr {
return result as? Data
}
return nil
}
}
// MARK: - JSON helpers.
extension Keychain {
private static let encoder: JSONEncoder = {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
return encoder
}()
private static let decoder: JSONDecoder = {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return decoder
}()
@discardableResult
class func set<T: Encodable>(_ value: T, forKey key: String) -> Bool {
if let encoded = try? encoder.encode(value) {
return set(encoded, forKey: key)
}
return false
}
class func get<T: Decodable>(_ key: String, as type: T.Type) -> T? {
if let data = get(key),
let decoded = try? decoder.decode(type, from: data)
{
return decoded
}
return nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment