diff --git a/Sources/Model/Data Flow/StateManager.swift b/Sources/Model/Data Flow/StateManager.swift index 335d6b8..9a1a0aa 100644 --- a/Sources/Model/Data Flow/StateManager.swift +++ b/Sources/Model/Data Flow/StateManager.swift @@ -23,12 +23,26 @@ public enum StateManager { struct State { /// The state's identifiers. - var ids: [UUID] + var ids: (first: UUID, second: UUID?) /// The state value. var value: Any? /// Whether to update in the next iteration. var update = false + /// Whether the state's identifiers contain a certain identifier. + /// - Parameter id: The identifier. + /// - Returns: Whether the id is contained. + func contains(id: UUID) -> Bool { + ids.first == id || ids.second == id + } + + /// Change the identifier to a new one. + /// - Parameter newID: The new identifier. + mutating func changeID(new newID: UUID) { + ids.second = ids.first + ids.first = newID + } + } /// Update all of the views. @@ -55,8 +69,8 @@ public enum StateManager { /// - value: The new value. static func setState(id: UUID, value: Any?) { if saveState { - guard let index = state.firstIndex(where: { $0.ids.contains(id) }) else { - state.append(.init(ids: [id], value: value)) + guard let index = state.firstIndex(where: { $0.contains(id: id) }) else { + state.append(.init(ids: (first: id, second: nil), value: value)) return } state[safe: index]?.value = value @@ -67,14 +81,14 @@ public enum StateManager { /// - Parameter id: The identifier. /// - Returns: The value. static func getState(id: UUID) -> Any? { - state[safe: state.firstIndex { $0.ids.contains(id) }]?.value + state[safe: state.firstIndex { $0.contains(id: id) }]?.value } /// Mark the state of a certain id as updated. /// - Parameter id: The identifier. static func updateState(id: UUID) { if saveState { - state[safe: state.firstIndex { $0.ids.contains(id) }]?.update = true + state[safe: state.firstIndex { $0.contains(id: id) }]?.update = true } } @@ -82,7 +96,7 @@ public enum StateManager { /// - Parameter id: The identifier. static func updatedState(id: UUID) { if saveState { - state[safe: state.firstIndex { $0.ids.contains(id) }]?.update = false + state[safe: state.firstIndex { $0.contains(id: id) }]?.update = false } } @@ -90,7 +104,7 @@ public enum StateManager { /// - Parameter id: The identifier. /// - Returns: Whether to update the state. static func getUpdateState(id: UUID) -> Bool { - state[safe: state.firstIndex { $0.ids.contains(id) }]?.update ?? false + state[safe: state.firstIndex { $0.contains(id: id) }]?.update ?? false } /// Change the identifier for a certain state value. @@ -99,7 +113,7 @@ public enum StateManager { /// - newID: The new identifier. static func changeID(old oldID: UUID, new newID: UUID) { if saveState { - state[safe: state.firstIndex { $0.ids.contains(oldID) }]?.ids.append(newID) + state[safe: state.firstIndex { $0.contains(id: oldID) }]?.changeID(new: newID) } } diff --git a/Tests/DemoApp/DemoApp.swift b/Tests/DemoApp/DemoApp.swift index 993459a..e3434fa 100644 --- a/Tests/DemoApp/DemoApp.swift +++ b/Tests/DemoApp/DemoApp.swift @@ -7,12 +7,12 @@ import SampleBackends @available(iOS 17, *) struct DemoView: View { - @State private var test = TestModel() + @State private var model = TestModel() var view: Body { Backend1.TestWidget1() - Backend1.Button(test.test) { - test.test = "\(Int.random(in: 1...10))" + Backend1.Button(model.test) { + model.test = "\(Int.random(in: 1...10))" } TestView() testContent @@ -66,6 +66,7 @@ struct DemoApp { } StateManager.addUpdateHandler { force in + print("#*") DemoView().updateStorage(storage, modifiers: [], updateProperties: force, type: backendType) } diff --git a/Tests/SampleBackends/Backend1.swift b/Tests/SampleBackends/Backend1.swift index 4476b0b..09f96cd 100644 --- a/Tests/SampleBackends/Backend1.swift +++ b/Tests/SampleBackends/Backend1.swift @@ -3,9 +3,9 @@ import Meta public enum Backend1 { public struct TestWidget1: BackendWidget { - + public init() { } - + public func container(modifiers: [(AnyView) -> AnyView], type: WidgetType.Type) -> ViewStorage { print("Init test widget 1") let storage = ViewStorage(nil) @@ -17,9 +17,9 @@ public enum Backend1 { print("Update test widget 1 (#\(storage.fields["test"] ?? ""))") storage.fields["test"] = (storage.fields["test"] as? Int ?? 0) + 1 } - + } - + public struct TestWidget3: BackendWidget { public init() { } @@ -50,16 +50,19 @@ public enum Backend1 { public func container(modifiers: [(any AnyView) -> any AnyView], type: WidgetType.Type) -> ViewStorage { print("Init button") + let storage = ViewStorage(nil) Task { try await Task.sleep(nanoseconds: 1_000_000_000) - action() + (storage.fields["action"] as? () -> Void)?() } - return .init(nil) + storage.fields["action"] = action + return storage } public func update(_ storage: ViewStorage, modifiers: [(any AnyView) -> any AnyView], updateProperties: Bool, type: WidgetType.Type) { if updateProperties { print("Update button (label = \(label))") + storage.fields["action"] = action } else { print("Do not update button (label = \(label))") } @@ -70,3 +73,4 @@ public enum Backend1 { public protocol BackendWidget: Widget { } } +