iOS
Swift

[Swift4] UserDefaultsとKeychainを綺麗に管理する!

はじめに

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)
    }
}

参考