はじめに
UserDefaultsとKeychainは各所から参照される存在であり、その責務を一点に集中させたいと考えました。
そこで、シングルトンの「Service構造体」を生成し、Subscripts・ジェネリクス・Enumを使ってまとめました。1
なお、KeychainAccessという有名なライブラリを使っています。
こう使えるようにした!
let sessionID = S.getKeychain(.SessionID)
let isFirstLaunch: Bool? = S.getUserDefaults(.isFirstLaunch)
いいかんじ〜
実装
Service.swift
import Foundation
import KeychainAccess
let S: Service.Type = Service.self
let SERVICE_NAME = "com.example.sensuikan1973"
struct Service {
private init(){}
static let keychain = Keychain(service: SERVICE_NAME)
static let userDefaults = UserDefaults.standard
}
// MARK: Keychain
enum Keychain_Keys: String {
case SessionID = "SessionID"
}
extension Service {
static func getKeychain(_ key: Keychain_Keys) -> String? {
return keychain[key.rawValue]
}
static func setKeychain(_ key: Keychain_Keys, _ value: String?) {
keychain[key.rawValue] = value
}
}
// MARK: UserDefaults
enum UserDefaults_Keys: String {
case isFirstLaunch = "isFirstLaunch"
}
extension Service {
static func setDefaultUserDefaults() {
userDefaults.register(defaults: [UserDefaults_Keys.isFirstLaunch.rawValue: true])
}
static func setUserDefaults<T>(_ key: UserDefaults_Keys, _ value: T) {
userDefaults[key] = value
}
static func getUserDefaults<T: Any>(_ key: UserDefaults_Keys) -> T? {
return userDefaults[key]
}
static func removeUserDefaults(_ key: UserDefaults_Keys) {
userDefaults.remove(key)
}
}
UserDefaults+subscript.swift
extension UserDefaults {
subscript<T: Any>(key: UserDefaults_Keys) -> T? {
get {
let value = object(forKey: key.rawValue)
return value as? T
}
set {
guard let newValue = newValue else {
removeObject(forKey: key.rawValue)
return
}
set(newValue, forKey: key.rawValue)
}
}
func remove(_ key: UserDefaults_Keys) {
removeObject(forKey: key.rawValue)
}
}
参考
- Swift4でUserDefaultsを簡単に扱う
- [Swift]ProtocolとEnumでSwiftライクな一元管理で綺麗なコードを書く工夫 : チェーンで参照する書き方について。本稿とは異なるアプローチです。