From 76f4a9a0fcdba9e5e4e3e7a91b78309ef6eaa410 Mon Sep 17 00:00:00 2001 From: "brunel.lee" Date: Fri, 5 Jan 2024 14:37:52 +0900 Subject: [PATCH] Add Binder for swiftui --- Sources/OneWay/Store.swift | 2 +- Sources/OneWay/ViewStore.swift | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Sources/OneWay/Store.swift b/Sources/OneWay/Store.swift index e8c3452..c92624e 100644 --- a/Sources/OneWay/Store.swift +++ b/Sources/OneWay/Store.swift @@ -40,7 +40,7 @@ where R.Action: Sendable, R.State: Sendable & Equatable { private let reducer: any Reducer private let continuation: AsyncStream.Continuation - private var isProcessing: Bool = false + public private(set) var isProcessing: Bool = false private var actionQueue: [Action] = [] private var bindingTask: Task? private var tasks: [TaskID: Task] = [:] diff --git a/Sources/OneWay/ViewStore.swift b/Sources/OneWay/ViewStore.swift index b5d7c09..4f6861e 100644 --- a/Sources/OneWay/ViewStore.swift +++ b/Sources/OneWay/ViewStore.swift @@ -26,7 +26,7 @@ where R.Action: Sendable, R.State: Sendable & Equatable { public let initialState: State /// The current state of a store. - public var state: State { + public private(set) var state: State { didSet { continuation.yield(state) states.send(state) @@ -97,3 +97,28 @@ where R.Action: Sendable, R.State: Sendable & Equatable { #if canImport(Combine) extension ViewStore: ObservableObject { } #endif + + +#if canImport(SwiftUI) +import SwiftUI + +extension ViewStore { + func binding(_ keyPath: WritableKeyPath) -> Binding { + Binding( + get: { self.state[keyPath: keyPath] }, + set: { value in + Task { + await self.store.justSetStateValue((value, keyPath)) + } + } + ) + } +} + +extension Store { + fileprivate func justSetStateValue(_ setter: (T, WritableKeyPath)) { + guard !isProcessing else { return } + self.state[keyPath: setter.1] = setter.0 + } +} +#endif