Skip to content

Instantly share code, notes, and snippets.

@mikeash
Last active October 4, 2017 15:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikeash/12a13c9ae8cd3e35aa31a84523dee483 to your computer and use it in GitHub Desktop.
Save mikeash/12a13c9ae8cd3e35aa31a84523dee483 to your computer and use it in GitHub Desktop.
// SCROLL DOWN //
import Foundation
protocol TSUD {
associatedtype Value: Codable
init()
static var defaultValue: Value { get }
var stringKey: String { get }
}
extension TSUD {
var stringKey: String {
return String(describing: Self.self)
}
}
private protocol OptionalP {
var isNil: Bool { get }
}
extension Optional: OptionalP {
var isNil: Bool { return self == nil }
}
extension TSUD {
static var value: Value {
get {
return get()
}
set {
set(newValue)
}
}
static func get(_ nsud: UserDefaults = .standard) -> Value {
return self.init()[.standard]
}
static func set(_ value: Value, _ nsud: UserDefaults = .standard) {
self.init()[.standard] = value
}
subscript(nsud: UserDefaults) -> Value {
get {
return decode(nsud.object(forKey: stringKey)) ?? Self.defaultValue
}
nonmutating set {
nsud.set(encode(newValue), forKey: stringKey)
}
}
private func decode(_ plist: Any?) -> Value? {
guard let plist = plist else { return nil }
guard let data = try? PropertyListSerialization.data(fromPropertyList: plist, format: .binary, options: 0) else { return nil }
return try? PropertyListDecoder().decode(Value.self, from: data)
}
private func encode(_ value: Value?) -> Any? {
guard let value = value else { return nil }
if let opt = value as? OptionalP, opt.isNil { return nil }
do {
let data = try PropertyListEncoder().encode([value])
let wrappedPlist = try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [Any]
return wrappedPlist?[0]
} catch {
return nil
}
}
}
// START HERE //
//struct opt: TSUD {
// static let defaultValue: Int? = nil
//}
//
//opt.value = nil
//
//struct nonopt: TSUD {
// static let defaultValue = 0
//}
//
//nonopt.value = 1
struct enableThingy: TSUD {
static let defaultValue = false
}
struct numberOfThingies: TSUD {
static let defaultValue = 0
}
struct optionalNumber: TSUD {
static let defaultValue: Int? = nil
}
enableThingy.value = false
enableThingy.value
UserDefaults.standard.object(forKey: "enableThingy")
enableThingy.value = true
enableThingy.value
UserDefaults.standard.object(forKey: "enableThingy")
numberOfThingies.value += 1
numberOfThingies.value
UserDefaults.standard.object(forKey: "numberOfThingies")
optionalNumber.value
UserDefaults.standard.object(forKey: "optionalNumber")
optionalNumber.value = 3
optionalNumber.value
UserDefaults.standard.object(forKey: "optionalNumber")
optionalNumber.value = nil
optionalNumber.value
UserDefaults.standard.object(forKey: "optionalNumber")
struct Widget: Codable {
var name: String
var purpose: String
var count: Int
}
struct lastWidget: TSUD {
static let defaultValue: Widget? = nil
}
lastWidget.value
lastWidget.value = Widget(name: "Plunger", purpose: "Plunging", count: 42)
UserDefaults.standard.object(forKey: "lastWidget")
lastWidget.value
lastWidget.value = nil
dump(UserDefaults.standard.object(forKey: "lastWidget"))
struct allWidgets: TSUD {
static let defaultValue: [Widget] = []
}
allWidgets.value
allWidgets.value.append(Widget(name: "Whatever", purpose: "\(UUID())", count: Int(Date.timeIntervalSinceReferenceDate)))
allWidgets.value
UserDefaults.standard.object(forKey: "allWidgets")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment