diff --git a/Sources/SwiftCrossUI/State/State.swift b/Sources/SwiftCrossUI/State/State.swift index 9b3219c68f..b090a3eb9d 100644 --- a/Sources/SwiftCrossUI/State/State.swift +++ b/Sources/SwiftCrossUI/State/State.swift @@ -5,7 +5,7 @@ import Foundation // - It supports ObservableObject // - It supports Optional @propertyWrapper -public struct State: DynamicProperty, StateProperty { +public struct State: DynamicProperty, ObservableProperty { class Storage { // This inner box is what stays constant between view updates. The // outer box (Storage) is used so that we can assign this box to @@ -55,7 +55,7 @@ public struct State: DynamicProperty, StateProperty { var storage: Storage - var didChange: Publisher { + public var didChange: Publisher { storage.box.didChange } @@ -109,7 +109,7 @@ public struct State: DynamicProperty, StateProperty { } } - func tryRestoreFromSnapshot(_ snapshot: Data) { + public func tryRestoreFromSnapshot(_ snapshot: Data) { guard let decodable = Value.self as? Codable.Type, let state = try? JSONDecoder().decode(decodable, from: snapshot) @@ -120,7 +120,7 @@ public struct State: DynamicProperty, StateProperty { storage.box.value = state as! Value } - func snapshot() throws -> Data? { + public func snapshot() throws -> Data? { if let value = storage.box as? Codable { return try JSONEncoder().encode(value) } else { @@ -129,7 +129,10 @@ public struct State: DynamicProperty, StateProperty { } } -protocol StateProperty { +/// Declaring conformance to ObservableProperty is required for +/// SwiftCrossUI to automatically register an observer on the +/// conforming object's Publisher. +public protocol ObservableProperty { var didChange: Publisher { get } func tryRestoreFromSnapshot(_ snapshot: Data) func snapshot() throws -> Data? diff --git a/Sources/SwiftCrossUI/ViewGraph/ViewGraphNode.swift b/Sources/SwiftCrossUI/ViewGraph/ViewGraphNode.swift index b80b848699..0d4ad09f33 100644 --- a/Sources/SwiftCrossUI/ViewGraph/ViewGraphNode.swift +++ b/Sources/SwiftCrossUI/ViewGraph/ViewGraphNode.swift @@ -116,7 +116,7 @@ public class ViewGraphNode: Sendable { ) } - guard let value = property.value as? StateProperty else { + guard let value = property.value as? ObservableProperty else { continue } diff --git a/Sources/SwiftCrossUI/ViewGraph/ViewGraphSnapshotter.swift b/Sources/SwiftCrossUI/ViewGraph/ViewGraphSnapshotter.swift index ea7cd436e7..7c94ab7d9e 100644 --- a/Sources/SwiftCrossUI/ViewGraph/ViewGraphSnapshotter.swift +++ b/Sources/SwiftCrossUI/ViewGraph/ViewGraphSnapshotter.swift @@ -55,7 +55,7 @@ public struct ViewGraphSnapshotter: ErasedViewGraphNodeTransformer { let mirror = Mirror(reflecting: view) for property in mirror.children { guard - let stateProperty = property as? StateProperty, + let stateProperty = property as? ObservableProperty, let propertyName = property.label, let encodedState = state[propertyName] else { @@ -80,7 +80,7 @@ public struct ViewGraphSnapshotter: ErasedViewGraphNodeTransformer { for property in mirror.children { guard let propertyName = property.label, - let property = property as? StateProperty, + let property = property as? ObservableProperty, let encodedState = try? property.snapshot() else { continue diff --git a/Sources/SwiftCrossUI/_App.swift b/Sources/SwiftCrossUI/_App.swift index 4d0a0a3624..1f9c8df2a8 100644 --- a/Sources/SwiftCrossUI/_App.swift +++ b/Sources/SwiftCrossUI/_App.swift @@ -66,7 +66,7 @@ class _App { ) } - guard let value = property.value as? StateProperty else { + guard let value = property.value as? ObservableProperty else { continue }