Only save the two most recent state identifiers

This commit is contained in:
david-swift 2024-06-30 16:56:06 +02:00
parent 2551c0a14d
commit 20b2fee279
3 changed files with 36 additions and 17 deletions

View File

@ -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)
}
}

View File

@ -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)
}

View File

@ -3,9 +3,9 @@ import Meta
public enum Backend1 {
public struct TestWidget1: BackendWidget {
public init() { }
public func container<WidgetType>(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<WidgetType>(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<WidgetType>(_ 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 { }
}