Skip to content

Instantly share code, notes, and snippets.

@mattyoung
Last active May 22, 2021 11:19
Show Gist options
  • Save mattyoung/ac9bae68cef40fc3bf9469b9b39e0a56 to your computer and use it in GitHub Desktop.
Save mattyoung/ac9bae68cef40fc3bf9469b9b39e0a56 to your computer and use it in GitHub Desktop.
import SwiftUI
public protocol ObservablePropertySource: ObservableObject {
static var shared: Self { get }
}
@propertyWrapper
public struct ObservableProperty<S: ObservablePropertySource, T>: DynamicProperty {
@ObservedObject private var source: S
private let keyPath: KeyPath<S, T>
public init(_ keyPath: KeyPath<S, T>) {
source = S.shared
self.keyPath = keyPath
}
public var wrappedValue: T {
source[keyPath: keyPath]
}
}
public final class Features: ObservablePropertySource {
public static let shared = Features()
private init() { }
@Published public var isDebugMenuEnabled = false
}
public final class AppSettings: ObservablePropertySource {
public static let shared = AppSettings()
private init() { }
@AppStorage("appSetting1") public var appSetting1: Int = 42
// could just be `static` and access directly without going through @wrapper
@AppStorage("appSetting2") public static var appSetting2: String = "Hello"
}
public final class SceneSettings: ObservableObject {
public static let shared = SceneSettings()
private init() { }
@SceneStorage("sceneValue1") public var sceneSetting1: Int = 54
@SceneStorage("sceneValue2") public var sceneSetting2: String = "World"
}
struct ContentView: View {
// @Feature(\.isDebugMenuEnabled) var showDebugMenu
// @AppSetting(\.appSetting1) var appSetting1
@ObservableProperty(\Features.isDebugMenuEnabled) var showDebugMenu
@ObservableProperty(\AppSettings.appSetting1) var appSetting1
var body: some View {
VStack {
Text("Hello, world!")
.padding()
if showDebugMenu {
Text("Debug Menu on")
} else {
Text("Debug Menu off")
}
Text("appSetting1 = \(appSetting1)")
// directly access static, better?
Text("appSetting2 = \(AppSettings.appSetting2)")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment