Skip to content

Commit 04431ad

Browse files
committed
Add extensions to ReactiveSwift Schedulers to support the
`animation` and `transaction` modifiers.
1 parent 819abba commit 04431ad

File tree

2 files changed

+123
-0
lines changed

2 files changed

+123
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#if canImport(SwiftUI)
2+
import SwiftUI
3+
import ReactiveSwift
4+
5+
extension Scheduler {
6+
/// Specifies an animation to perform when an action is scheduled.
7+
///
8+
/// - Parameter animation: An animation to be performed.
9+
/// - Returns: A scheduler that performs an animation when a scheduled action is run.
10+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
11+
public func animation(_ animation: Animation? = .default) -> Scheduler {
12+
ActionWrappingScheduler(scheduler: self, wrapper: .animation(animation))
13+
}
14+
15+
/// Wraps scheduled actions in a transaction.
16+
///
17+
/// - Parameter transaction: A transaction.
18+
/// - Returns: A scheduler that wraps scheduled actions in a transaction.
19+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
20+
public func transaction(_ transaction: Transaction) -> Scheduler {
21+
ActionWrappingScheduler(scheduler: self, wrapper: .transaction(transaction))
22+
}
23+
}
24+
25+
extension DateScheduler {
26+
/// Specifies an animation to perform when an action is scheduled.
27+
///
28+
/// - Parameter animation: An animation to be performed.
29+
/// - Returns: A scheduler that performs an animation when a scheduled action is run.
30+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
31+
public func animation(_ animation: Animation? = .default) -> DateScheduler {
32+
ActionWrappingDateScheduler(scheduler: self, wrapper: .animation(animation))
33+
}
34+
35+
/// Wraps scheduled actions in a transaction.
36+
///
37+
/// - Parameter transaction: A transaction.
38+
/// - Returns: A scheduler that wraps scheduled actions in a transaction.
39+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
40+
public func transaction(_ transaction: Transaction) -> DateScheduler {
41+
ActionWrappingDateScheduler(scheduler: self, wrapper: .transaction(transaction))
42+
}
43+
}
44+
45+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
46+
private enum ActionWrapper {
47+
case animation(Animation?)
48+
case transaction(Transaction)
49+
}
50+
51+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
52+
public final class ActionWrappingScheduler: Scheduler {
53+
private let scheduler: Scheduler
54+
private let wrapper: ActionWrapper
55+
56+
fileprivate init(scheduler: Scheduler, wrapper: ActionWrapper) {
57+
self.scheduler = scheduler
58+
self.wrapper = wrapper
59+
}
60+
61+
public func schedule(_ action: @escaping () -> Void) -> Disposable? {
62+
scheduler.schedule {
63+
switch self.wrapper {
64+
case let .animation(animation):
65+
withAnimation(animation, action)
66+
case let .transaction(transaction):
67+
withTransaction(transaction, action)
68+
}
69+
}
70+
}
71+
}
72+
73+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
74+
public final class ActionWrappingDateScheduler: DateScheduler {
75+
public var currentDate: Date {
76+
scheduler.currentDate
77+
}
78+
79+
private let scheduler: DateScheduler
80+
private let wrapper: ActionWrapper
81+
82+
fileprivate init(scheduler: DateScheduler, wrapper: ActionWrapper) {
83+
self.scheduler = scheduler
84+
self.wrapper = wrapper
85+
}
86+
87+
public func schedule(_ action: @escaping () -> Void) -> Disposable? {
88+
scheduler.schedule {
89+
switch self.wrapper {
90+
case let .animation(animation):
91+
withAnimation(animation, action)
92+
case let .transaction(transaction):
93+
withTransaction(transaction, action)
94+
}
95+
}
96+
}
97+
98+
public func schedule(after date: Date, action: @escaping () -> Void) -> Disposable? {
99+
scheduler.schedule(after: date) {
100+
switch self.wrapper {
101+
case let .animation(animation):
102+
withAnimation(animation, action)
103+
case let .transaction(transaction):
104+
withTransaction(transaction, action)
105+
}
106+
}
107+
}
108+
109+
public func schedule(after date: Date, interval: DispatchTimeInterval, leeway: DispatchTimeInterval, action: @escaping () -> Void) -> Disposable? {
110+
scheduler.schedule(after: date, interval: interval, leeway: leeway) {
111+
switch self.wrapper {
112+
case let .animation(animation):
113+
withAnimation(animation, action)
114+
case let .transaction(transaction):
115+
withTransaction(transaction, action)
116+
}
117+
}
118+
}
119+
}
120+
#endif

Sources/ComposableArchitecture/SwiftUI/Animation.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#if canImport(SwiftUI)
12
import SwiftUI
23

34
extension ViewStore {
@@ -6,9 +7,11 @@ extension ViewStore {
67
/// - Parameters:
78
/// - action: An action.
89
/// - animation: An animation.
10+
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
911
public func send(_ action: Action, animation: Animation?) {
1012
withAnimation(animation) {
1113
self.send(action)
1214
}
1315
}
1416
}
17+
#endif

0 commit comments

Comments
 (0)