Skip to content

Commit 99238f0

Browse files
committed
[refactor]: Remove ReactiveSwift from Workflow public interface
BREAKING CHANGE: This changes the public interface of WorkflowHost and WorkflowHostingController. The rendering property is now a read only property of the Rendering There is a new renderingPublisher property for a Combine publisher for renderings The output Signal property has been removed and moved to an extension in WorkflowReactiveSwift There is a new outputPublisher property for a Combine publisher for output
1 parent 22b5dbf commit 99238f0

21 files changed

+279
-235
lines changed

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ let package = Package(
6868

6969
.target(
7070
name: "Workflow",
71-
dependencies: ["ReactiveSwift"],
7271
path: "Workflow/Sources"
7372
),
73+
7474
.target(
7575
name: "WorkflowTesting",
7676
dependencies: [

Samples/Project.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ let project = Project(
158158
.unitTest(
159159
for: "Workflow",
160160
sources: "../Workflow/Tests/**",
161-
dependencies: [.external(name: "Workflow")]
161+
dependencies: [
162+
.external(name: "ReactiveSwift"),
163+
.external(name: "Workflow"),
164+
]
162165
),
163166
.unitTest(
164167
for: "WorkflowTesting",

Samples/Tutorial/Frameworks/Tutorial5Complete/Tests/RootWorkflowTests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ class RootWorkflowTests: XCTestCase {
8787

8888
// First rendering is just the welcome screen. Update the name.
8989
do {
90-
let backStack = workflowHost.rendering.value
90+
let backStack = workflowHost.rendering
9191
XCTAssertEqual(1, backStack.items.count)
9292

9393
guard let welcomeScreen = backStack.items[0].screen.wrappedScreen as? WelcomeScreen else {
@@ -100,7 +100,7 @@ class RootWorkflowTests: XCTestCase {
100100

101101
// Log in and go to the todo list.
102102
do {
103-
let backStack = workflowHost.rendering.value
103+
let backStack = workflowHost.rendering
104104
XCTAssertEqual(1, backStack.items.count)
105105

106106
guard let welcomeScreen = backStack.items[0].screen.wrappedScreen as? WelcomeScreen else {
@@ -113,7 +113,7 @@ class RootWorkflowTests: XCTestCase {
113113

114114
// Expect the todo list to be rendered. Edit the first todo.
115115
do {
116-
let backStack = workflowHost.rendering.value
116+
let backStack = workflowHost.rendering
117117
XCTAssertEqual(2, backStack.items.count)
118118

119119
guard let _ = backStack.items[0].screen.wrappedScreen as? WelcomeScreen else {
@@ -134,7 +134,7 @@ class RootWorkflowTests: XCTestCase {
134134

135135
// Selected a todo to edit. Expect the todo edit screen.
136136
do {
137-
let backStack = workflowHost.rendering.value
137+
let backStack = workflowHost.rendering
138138
XCTAssertEqual(3, backStack.items.count)
139139

140140
guard let _ = backStack.items[0].screen.wrappedScreen as? WelcomeScreen else {
@@ -158,7 +158,7 @@ class RootWorkflowTests: XCTestCase {
158158

159159
// Save the selected todo.
160160
do {
161-
let backStack = workflowHost.rendering.value
161+
let backStack = workflowHost.rendering
162162
XCTAssertEqual(3, backStack.items.count)
163163

164164
guard let _ = backStack.items[0].screen.wrappedScreen as? WelcomeScreen else {
@@ -204,7 +204,7 @@ class RootWorkflowTests: XCTestCase {
204204

205205
// Expect the todo list. Validate the title was updated.
206206
do {
207-
let backStack = workflowHost.rendering.value
207+
let backStack = workflowHost.rendering
208208
XCTAssertEqual(2, backStack.items.count)
209209

210210
guard let _ = backStack.items[0].screen.wrappedScreen as? WelcomeScreen else {

Workflow/Sources/WorkflowHost.swift

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import ReactiveSwift
17+
import Combine
1818

1919
/// Defines a type that receives debug information about a running workflow hierarchy.
2020
public protocol WorkflowDebugger {
@@ -30,18 +30,30 @@ public protocol WorkflowDebugger {
3030
func didUpdate(snapshot: WorkflowHierarchyDebugSnapshot, updateInfo: WorkflowUpdateDebugInfo)
3131
}
3232

33-
/// Manages an active workflow hierarchy.
34-
public final class WorkflowHost<WorkflowType: Workflow> {
35-
private let (outputEvent, outputEventObserver) = Signal<WorkflowType.Output, Never>.pipe()
33+
public protocol WorkflowOutputPublisher {
34+
associatedtype Output
35+
36+
var outputPublisher: AnyPublisher<Output, Never> { get }
37+
}
3638

39+
/// Manages an active workflow hierarchy.
40+
public final class WorkflowHost<WorkflowType: Workflow>: WorkflowOutputPublisher {
3741
// @testable
3842
let rootNode: WorkflowNode<WorkflowType>
3943

40-
private let mutableRendering: MutableProperty<WorkflowType.Rendering>
44+
private let renderingSubject: CurrentValueSubject<WorkflowType.Rendering, Never>
45+
private let outputSubject = PassthroughSubject<WorkflowType.Output, Never>()
4146

4247
/// Represents the `Rendering` produced by the root workflow in the hierarchy. New `Rendering` values are produced
4348
/// as state transitions occur within the hierarchy.
44-
public let rendering: Property<WorkflowType.Rendering>
49+
public var rendering: WorkflowType.Rendering {
50+
renderingSubject.value
51+
}
52+
53+
/// A Publisher containing rendering events produced by the root workflow in the hierarchy.
54+
public var renderingPublisher: AnyPublisher<WorkflowType.Rendering, Never> {
55+
renderingSubject.eraseToAnyPublisher()
56+
}
4557

4658
/// Context object to pass down to descendant nodes in the tree.
4759
let context: HostContext
@@ -78,8 +90,8 @@ public final class WorkflowHost<WorkflowType: Workflow> {
7890
parentSession: nil
7991
)
8092

81-
self.mutableRendering = MutableProperty(rootNode.render())
82-
self.rendering = Property(mutableRendering)
93+
self.renderingSubject = CurrentValueSubject(rootNode.render())
94+
8395
rootNode.enableEvents()
8496

8597
debugger?.didEnterInitialState(snapshot: rootNode.makeDebugSnapshot())
@@ -110,12 +122,12 @@ public final class WorkflowHost<WorkflowType: Workflow> {
110122
private func handle(output: WorkflowNode<WorkflowType>.Output) {
111123
let shouldRender = !shouldSkipRenderForOutput(output)
112124
if shouldRender {
113-
mutableRendering.value = rootNode.render()
125+
renderingSubject.send(rootNode.render())
114126
}
115127

116128
// Always emit an output, regardless of whether a render occurs
117129
if let outputEvent = output.outputEvent {
118-
outputEventObserver.send(value: outputEvent)
130+
outputSubject.send(outputEvent)
119131
}
120132

121133
debugger?.didUpdate(
@@ -129,9 +141,9 @@ public final class WorkflowHost<WorkflowType: Workflow> {
129141
}
130142
}
131143

132-
/// A signal containing output events emitted by the root workflow in the hierarchy.
133-
public var output: Signal<WorkflowType.Output, Never> {
134-
outputEvent
144+
/// A publisher containing output events emitted by the root workflow in the hierarchy.
145+
public var outputPublisher: AnyPublisher<WorkflowType.Output, Never> {
146+
outputSubject.eraseToAnyPublisher()
135147
}
136148
}
137149

Workflow/Tests/AnyWorkflowTests.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import ReactiveSwift
17+
import Combine
1818
import XCTest
1919
@testable import Workflow
2020

@@ -40,19 +40,21 @@ public class AnyWorkflowTests: XCTestCase {
4040
let host = WorkflowHost(workflow: OnOutputWorkflow())
4141

4242
let renderingExpectation = expectation(description: "Waiting for rendering")
43-
host.rendering.producer.startWithValues { rendering in
43+
let cancellable = host.renderingPublisher.sink { rendering in
4444
if rendering {
4545
renderingExpectation.fulfill()
4646
}
4747
}
4848

4949
let outputExpectation = expectation(description: "Waiting for output")
50-
host.output.observeValues { output in
50+
let outputCancellable = host.outputPublisher.sink { output in
5151
if output {
5252
outputExpectation.fulfill()
5353
}
5454
}
5555
wait(for: [renderingExpectation, outputExpectation], timeout: 1)
56+
cancellable.cancel()
57+
outputCancellable.cancel()
5658
}
5759

5860
func testOnlyWrapsOnce() {

0 commit comments

Comments
 (0)