From 28907b417b08d1f56fb88d55479b705936378480 Mon Sep 17 00:00:00 2001 From: Tadeas Kriz Date: Tue, 21 May 2024 09:48:34 -0400 Subject: [PATCH] Add a third `collect` view modifier. --- .../runtime/SwiftUIFlowObservingGenerator.kt | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/phases/runtime/SwiftUIFlowObservingGenerator.kt b/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/phases/runtime/SwiftUIFlowObservingGenerator.kt index bbbe506e..05c66c30 100644 --- a/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/phases/runtime/SwiftUIFlowObservingGenerator.kt +++ b/SKIE/kotlin-compiler/core/src/commonMain/kotlin/co/touchlab/skie/phases/runtime/SwiftUIFlowObservingGenerator.kt @@ -47,7 +47,7 @@ object SwiftUIFlowObservingGenerator { let viewModel = SharedViewModel() @State - var counter: Int = 0 + var counter: KotlinInt = 0 var body: some View { Text("Tick #\(counter)") @@ -65,6 +65,46 @@ object SwiftUIFlowObservingGenerator { } } + /** + A view modifier used to collect a SKIE-bridged Flow into a SwiftUI Binding, transforming the value before assigning. + + The flow is being collected using the `task` modifier, + sharing the same lifecycle. + + In the following example we collect a `Flow` property `counter` + from the `SharedViewModel` into a `@State` property in our view. + + ```swift + struct ExampleView: View { + let viewModel = SharedViewModel() + + @State + var counter: Int = 0 + + var body: some View { + Text("Tick #\(counter)") + .collect(flow: viewModel.counter, into: ${'$'}counter) + } + } + ``` + + - parameter flow: A SKIE-bridged Flow you with to collect. + - parameter binding: A binding to a property where each new value will be set to. + - parameter transform: An async closure to transform any value emitted by the flow into a one expected by the binding. + Returning `nil` from this closure will reject the value. + */ + public func collect( + flow: Flow, + into binding: SwiftUI.Binding, + transform: @escaping (Flow.Element) async -> U? + ) -> some SwiftUI.View { + collect(flow: flow) { newValue in + if let newTransformedValue = await transform(newValue) { + binding.wrappedValue = newTransformedValue + } + } + } + /** A view modifier used to collect a SKIE-bridged Flow and perform a closere with each received value.