Skip to content

Instantly share code, notes, and snippets.

@bermudalocket
Last active August 29, 2023 00:47
Show Gist options
  • Save bermudalocket/776c8266e7443b6222f87360d5d46316 to your computer and use it in GitHub Desktop.
Save bermudalocket/776c8266e7443b6222f87360d5d46316 to your computer and use it in GitHub Desktop.
import Combine
import Foundation
let preferenceKey = "com.bermudalocket.myapp"
@propertyWrapper
struct Persistable<T> {
let key: String
let publisher: CurrentValueSubject<T, Never>
var projectedValue: Persistable<T> { return self }
var wrappedValue: T {
get {
self.publisher.value
}
set {
publisher.send(newValue)
UserDefaults.standard.set(newValue, forKey: self.key)
}
}
init(_ key: String, defaultValue: T) {
self.key = "\(preferenceKey).\(key)"
var value: T = defaultValue
if let currentValue = UserDefaults.standard.object(forKey: self.key) as? T {
value = currentValue
}
self.publisher = CurrentValueSubject<T, Never>(value)
}
}
class Preferences {
static let shared = Preferences()
@Persistable("blur", defaultValue: 10) var blur: Double
@Persistable("vibrancy", defaultValue: 17.5) var vibrancy: Double
@Persistable("tint", defaultValue: .someEnumValue) var tint: SomeEnumType
}
class SomePreferenceImplClass {
var cancellables = [Cancellable]()
var blur: Double
init() {
let cancellable = Preferences.shared.$blur.publisher.sink(receiveValue: { blur in
self.blur = blur
})
self.cancellables.append(cancellable)
}
deinit {
self.cancellables.forEach { $0.cancel() }
}
}
@SuperWomble
Copy link

Using an Enum type will result in a fatal error. ([User Defaults] Attempt to set a non-property-list object). Regards.

@JustinGanzer
Copy link

Crashes as well when optionals are used since you can not set userdefaults to nil, though that's easy to circumvent with the widely adopted AnyOptional protocol.

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