Skip to content

Instantly share code, notes, and snippets.

@mezhevikin
Last active July 11, 2023 13:19
Show Gist options
  • Save mezhevikin/03d6971bb0761a5e344b4392648ceedc to your computer and use it in GitHub Desktop.
Save mezhevikin/03d6971bb0761a5e344b4392648ceedc to your computer and use it in GitHub Desktop.
ContentView2.swift
import SwiftUI
struct ContentView: View {
@StateObject var settings = Settings()
var body: some View {
VStack(spacing: 20) {
Text(settings.isActive ? "Yes" : "No")
Button("Toogle") {
settings.isActive.toggle()
}
}
}
}
class Settings: ObservableObject {
@Persistent(key: "isActive")
var isActive: Bool = false
}
@propertyWrapper
struct Persistent<Value>: DynamicProperty {
let key: String
let defaultValue: Value
let store: UserDefaults
init(
wrappedValue defaultValue: Value,
key: String,
store: UserDefaults = .standard
) {
self.defaultValue = defaultValue
self.key = key
self.store = store
self.value = State<Value>(
initialValue: store.object(forKey: key) as? Value ?? defaultValue
)
}
private var value: State<Value>
var wrappedValue: Value {
get {
value.wrappedValue
}
nonmutating set {
DispatchQueue.main.async {
value.wrappedValue = newValue
if let optional = newValue as? AnyOptional, optional.isNil {
store.removeObject(forKey: key)
} else {
store.set(newValue, forKey: key)
}
}
}
}
var projectedValue: Binding<Value> {
value.projectedValue
}
}
extension Persistent where Value: ExpressibleByNilLiteral {
init(key: String, store: UserDefaults = .standard) {
self.init(wrappedValue: nil, key: key, store: store)
}
}
protocol AnyOptional {
var isNil: Bool { get }
}
extension Optional: AnyOptional {
var isNil: Bool { self == nil }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment