Skip to content

Instantly share code, notes, and snippets.

@HarshilShah
Created October 18, 2019 15:23
Show Gist options
  • Save HarshilShah/9434b1aa99929f9e0a662d3599908bdd to your computer and use it in GitHub Desktop.
Save HarshilShah/9434b1aa99929f9e0a662d3599908bdd to your computer and use it in GitHub Desktop.
An observable property wrapper for UserDefaults
import Foundation
import Combine
@propertyWrapper
final class UserDefault<Wrapped>: NSObject, ObservableObject {
typealias Validator = (Wrapped) -> (Wrapped)
private let suite: UserDefaults
private let key: String
private let defaultValue: Wrapped
private let validator: Validator
init(suite: UserDefaults = .standard, key: String, defaultValue: Wrapped, validator: @escaping Validator = ({ $0 })) {
self.suite = suite
self.key = key
self.defaultValue = defaultValue
self.validator = validator
super.init()
suite.register(defaults: [key: defaultValue])
suite.addObserver(self, forKeyPath: key, options: .prior, context: nil)
}
var wrappedValue: Wrapped {
get { validator(suite.object(forKey: key) as? Wrapped ?? defaultValue) }
set { suite.set(validator(newValue), forKey: key) }
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
objectWillChange.send()
}
}
@SuperWomble
Copy link

Could you please explain how to use this? How does one get a Publisher for the defaults-backed value? Thank you.

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