Skip to content

Instantly share code, notes, and snippets.

@andyyhope
Last active November 15, 2020 10:27
Show Gist options
  • Save andyyhope/b2fbd9cbbc48a7d9d56ca3feb55bc1f5 to your computer and use it in GitHub Desktop.
Save andyyhope/b2fbd9cbbc48a7d9d56ca3feb55bc1f5 to your computer and use it in GitHub Desktop.
//:
//: UserDefaultable.swift
//:
//: Created by Andyy Hope on 18/08/2016.
//: Twitter: @andyyhope
//: Medium: Andyy Hope, https://medium.com/@AndyyHope
import Foundation
// MARK: - Key Namespaceable
protocol KeyNamespaceable { }
extension KeyNamespaceable {
private static func namespace(_ key: String) -> String {
return "\(Self.self).\(key)"
}
static func namespace<T: RawRepresentable>(_ key: T) -> String where T.RawValue == String {
return namespace(key.rawValue)
}
}
// MARK: - Bool Defaults
protocol BoolUserDefaultable : KeyNamespaceable {
associatedtype BoolDefaultKey : RawRepresentable
}
extension BoolUserDefaultable where BoolDefaultKey.RawValue == String {
// Set
static func set(_ bool: Bool, forKey key: BoolDefaultKey) {
let key = namespace(key)
UserDefaults.standard.set(bool, forKey: key)
}
// Get
static func bool(forKey key: BoolDefaultKey) -> Bool {
let key = namespace(key)
return UserDefaults.standard.bool(forKey: key)
}
}
// MARK: - Float Defaults
protocol FloatUserDefaultable : KeyNamespaceable {
associatedtype FloatDefaultKey : RawRepresentable
}
extension FloatUserDefaultable where FloatDefaultKey.RawValue == String {
// Set
static func set(_ float: Float, forKey key: FloatDefaultKey) {
let key = namespace(key)
UserDefaults.standard.set(float, forKey: key)
}
// Get
static func float(forKey key: FloatDefaultKey) -> Float {
let key = namespace(key)
return UserDefaults.standard.float(forKey: key)
}
}
// MARK: - Integer Defaults
protocol IntegerUserDefaultable : KeyNamespaceable {
associatedtype IntegerDefaultKey : RawRepresentable
}
extension IntegerUserDefaultable where IntegerDefaultKey.RawValue == String {
// Set
static func set(_ integer: Int, forKey key: IntegerDefaultKey) {
let key = namespace(key)
UserDefaults.standard.set(integer, forKey: key)
}
// Get
static func integer(forKey key: IntegerDefaultKey) -> Int {
let key = namespace(key)
return UserDefaults.standard.integer(forKey: key)
}
}
// MARK: - Object Defaults
protocol ObjectUserDefaultable : KeyNamespaceable {
associatedtype ObjectDefaultKey : RawRepresentable
}
extension ObjectUserDefaultable where ObjectDefaultKey.RawValue == String {
// Set
static func set(_ object: AnyObject, forKey key: ObjectDefaultKey) {
let key = namespace(key)
UserDefaults.standard.set(object, forKey: key)
}
// Get
static func object(forKey key: ObjectDefaultKey) -> Any? {
let key = namespace(key)
return UserDefaults.standard.object(forKey: key)
}
}
// MARK: - Double Defaults
protocol DoubleUserDefaultable : KeyNamespaceable {
associatedtype DoubleDefaultKey : RawRepresentable
}
extension DoubleUserDefaultable where DoubleDefaultKey.RawValue == String {
// Set
static func set(_ double: Double, forKey key: DoubleDefaultKey) {
let key = namespace(key)
UserDefaults.standard.set(double, forKey: key)
}
// Get
static func double(forKey key: DoubleDefaultKey) -> Double {
let key = namespace(key)
return UserDefaults.standard.double(forKey: key)
}
}
// MARK: - URL Defaults
protocol URLUserDefaultable : KeyNamespaceable {
associatedtype URLDefaultKey : RawRepresentable
}
extension URLUserDefaultable where URLDefaultKey.RawValue == String {
// Set
static func set(_ url: URL, forKey key: URLDefaultKey) {
let key = namespace(key)
UserDefaults.standard.set(url, forKey: key)
}
// Get
static func url(forKey key: URLDefaultKey) -> URL? {
let key = namespace(key)
return UserDefaults.standard.url(forKey: key)
}
}
// MARK: - Use
// Preparation
extension UserDefaults {
struct Account : BoolUserDefaultable {
private init() { }
enum BoolDefaultKey : String {
case isUserLoggedIn
}
}
}
// Set
UserDefaults.Account.set(true, forKey: .isUserLoggedIn)
// Get
let isUserLoggedIn = UserDefaults.Account.bool(forKey: .isUserLoggedIn)
@zboralski
Copy link

This is really cool!

@andyyhope how do you get the keypath to use in UserDefaults.standard.observe?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment