Skip to content

Commit 2edaea9

Browse files
committed
Add pause and resume API's to Loop
On some scenarios, it's useful to "pause" the `Loop` so that we stop processing events for some reason (e.g. to stop a `Loop` backed Service). Following the same reasoning, it becomes necessary to have a "resume" mechanism so that the Loop starts processing events again. Given `Loop` now starts automatically and `stop` is designed as a tear down mechanism to be used on dealloc and dispose all observations, some new API's are required so that we can unplug/replug feedbacks to achieve the above mentioned pause/resume behavior. ## Changes - Create new `plugFeedbacks` and `unplugFeedbacks` API's in `Floodgate`, which establish and dispose feedbacks observations, respectively. Floodgate now retains the feedbacks passed in on `bootstrap` to use them on `plugFeedbacks`. - Add `pause` and `resume` API's to `LoopBoxBase`. - Implement `pause` and `resume` API's in `RootLoopBox`, which unplug and plug the feedbacks on the `Floodgate`, respectively. - Implement `pause` and `resume` API's in `ScopedLoopBox`, which forward the calls to their root, respectively.
1 parent 49404fc commit 2edaea9

File tree

4 files changed

+43
-3
lines changed

4 files changed

+43
-3
lines changed

Diff for: Loop.podspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
1616
s.watchos.deployment_target = '2.0'
1717
s.tvos.deployment_target = '9.0'
1818
s.source = { :git => "https://github.com/ReactiveCocoa/Loop.git", :tag => "#{s.version}" }
19-
s.source_files = "Loop/*.{swift}"
19+
s.source_files = "Loop/**/*.{swift}"
2020

2121
s.cocoapods_version = ">= 1.7.0"
2222
s.swift_versions = ["5.0", "5.1"]

Diff for: Loop/Floodgate.swift

+14-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ final class Floodgate<State, Event>: FeedbackEventConsumer<Event> {
2929

3030
private let queue = Atomic(QueueState())
3131
private let reducer: (inout State, Event) -> Void
32-
private let feedbackDisposables = CompositeDisposable()
32+
private var feedbacks: [Loop<State, Event>.Feedback] = []
33+
private var feedbackDisposables = CompositeDisposable()
3334

3435
init(state: State, reducer: @escaping (inout State, Event) -> Void) {
3536
self.state = state
@@ -40,7 +41,13 @@ final class Floodgate<State, Event>: FeedbackEventConsumer<Event> {
4041
dispose()
4142
}
4243

43-
func bootstrap(with feedbacks: [FeedbackLoop<State, Event>.Feedback]) {
44+
func bootstrap(with feedbacks: [Loop<State, Event>.Feedback]) {
45+
self.feedbacks = feedbacks
46+
47+
plugFeedbacks()
48+
}
49+
50+
func plugFeedbacks() {
4451
for feedback in feedbacks {
4552
// Pass `producer` which has replay-1 semantic.
4653
feedbackDisposables += feedback.events(producer, self)
@@ -51,6 +58,11 @@ final class Floodgate<State, Event>: FeedbackEventConsumer<Event> {
5158
}
5259
}
5360

61+
func unplugFeedbacks() {
62+
feedbackDisposables.dispose()
63+
feedbackDisposables = CompositeDisposable()
64+
}
65+
5466
override func process(_ event: Event, for token: Token) {
5567
enqueue(event, for: token)
5668

Diff for: Loop/LoopBox.swift

+20
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ internal class ScopedLoopBox<RootState, RootEvent, ScopedState, ScopedEvent>: Lo
4242
event: { [eventTransform] in eventTransform(event($0)) }
4343
)
4444
}
45+
46+
override func pause() {
47+
root.pause()
48+
}
49+
50+
override func resume() {
51+
root.resume()
52+
}
4553
}
4654

4755
internal class RootLoopBox<State, Event>: LoopBoxBase<State, Event> {
@@ -81,6 +89,14 @@ internal class RootLoopBox<State, Event>: LoopBoxBase<State, Event> {
8189
ScopedLoopBox(root: self, value: scope, event: event)
8290
}
8391

92+
override func pause() {
93+
floodgate.unplugFeedbacks()
94+
}
95+
96+
override func resume() {
97+
floodgate.plugFeedbacks()
98+
}
99+
84100
func start(with feedbacks: [Loop<State, Event>.Feedback]) {
85101
floodgate.bootstrap(with: feedbacks + [input.feedback])
86102
}
@@ -113,6 +129,10 @@ internal class LoopBoxBase<State, Event> {
113129
) -> LoopBoxBase<S, E> {
114130
subclassMustImplement()
115131
}
132+
133+
func pause() { subclassMustImplement() }
134+
135+
func resume() { subclassMustImplement() }
116136
}
117137

118138
@inline(never)

Diff for: Loop/Public/Loop.swift

+8
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,14 @@ public final class Loop<State, Event> {
5353
box: box.scoped(to: scope, event: event)
5454
)
5555
}
56+
57+
public func pause() {
58+
box.pause()
59+
}
60+
61+
public func resume() {
62+
box.resume()
63+
}
5664
}
5765

5866
extension Loop {

0 commit comments

Comments
 (0)