diff --git a/Example/Example/ExampleApp.swift b/Example/Example/ExampleApp.swift index e099ae3..53bd8f8 100644 --- a/Example/Example/ExampleApp.swift +++ b/Example/Example/ExampleApp.swift @@ -1,10 +1,17 @@ import SwiftUI +import Perception @main struct ExampleApp: App { + let model = CounterModel() + var body: some Scene { - WindowGroup { - ContentView(model: CounterModel()) + WithPerceptionTracking { + let _ = print("!!!") +// let _ = model.count + WindowGroup { + ContentView(model: model) + } } } } diff --git a/Sources/Perception/Environment.swift b/Sources/Perception/Environment.swift new file mode 100644 index 0000000..0a38986 --- /dev/null +++ b/Sources/Perception/Environment.swift @@ -0,0 +1,62 @@ +import SwiftUI + +extension Environment { + @available(iOS, introduced: 13, obsoleted: 17) + @available(macOS, introduced: 10.15, obsoleted: 14) + @available(tvOS, introduced: 13, obsoleted: 17) + @available(watchOS, introduced: 6, obsoleted: 10) + @available(visionOS, unavailable) + @_disfavoredOverload + public init(_ objectType: Value.Type) where Value: AnyObject & Perceptible { + self.init(\.[unwrap: \Value.self]) + } + + @available(iOS, introduced: 13, obsoleted: 17) + @available(macOS, introduced: 10.15, obsoleted: 14) + @available(tvOS, introduced: 13, obsoleted: 17) + @available(watchOS, introduced: 6, obsoleted: 10) + @available(visionOS, unavailable) + @_disfavoredOverload + public init(_ objectType: T.Type) where Value == T? { + self.init(\.[\T.self]) + } +} + +extension View { + @available(iOS, introduced: 13, obsoleted: 17) + @available(macOS, introduced: 10.15, obsoleted: 14) + @available(tvOS, introduced: 13, obsoleted: 17) + @available(watchOS, introduced: 6, obsoleted: 10) + @available(visionOS, unavailable) + public func environment(_ object: T?) -> some View { + self.environment(\.[\T.self], object) + } +} + +private struct PerceptibleKey: EnvironmentKey { + static var defaultValue: T? { nil } +} + +extension EnvironmentValues { + fileprivate subscript(_: KeyPath) -> T? { + get { self[PerceptibleKey.self] } + set { self[PerceptibleKey.self] = newValue } + } +} + +extension EnvironmentValues { + fileprivate subscript(unwrap _: KeyPath) -> T { + get { + guard let object = self[\T.self] else { + fatalError( + """ + No perceptible object of type \(T.self) found. A View.environment(_:) for \(T.self) may \ + be missing as an ancestor of this view. + """ + ) + } + return object + } + set { self[\T.self] = newValue } + } +}