Skip to content

Commit 40d4215

Browse files
drucelweissep4checo
authored andcommitted
Add support for SwiftUI withTransaction API (#1824)
* Adds withTransaction extension * reduce code * fix typo * Adds transaction support to Send and ViewStore.send * Update Sources/ComposableArchitecture/Effect.swift * Update Sources/ComposableArchitecture/ViewStore.swift Co-authored-by: Stephen Celis <[email protected]> (cherry picked from commit b4e6e83c982fd715fd9049de205c46f91501fa1d) # Conflicts: # Sources/ComposableArchitecture/Effect.swift # Sources/ComposableArchitecture/Effects/Animation.swift
1 parent fe1adc0 commit 40d4215

File tree

3 files changed

+72
-33
lines changed

3 files changed

+72
-33
lines changed

Sources/ComposableArchitecture/Effect.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,17 @@ public struct Send<Action> {
379379
/// - action: An action.
380380
/// - animation: An animation.
381381
public func callAsFunction(_ action: Action, animation: Animation?) {
382+
callAsFunction(action, transaction: Transaction(animation: animation))
383+
}
384+
385+
/// Sends an action back into the system from an effect with transaction.
386+
///
387+
/// - Parameters:
388+
/// - action: An action.
389+
/// - transaction: A transaction.
390+
public func callAsFunction(_ action: Action, transaction: Transaction) {
382391
guard !Task.isCancelled else { return }
383-
withAnimation(animation) {
392+
withTransaction(transaction) {
384393
self(action)
385394
}
386395
}
Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,50 @@
11
#if canImport(SwiftUI)
22
import ReactiveSwift
3-
import SwiftUI
3+
import SwiftUI
44

55
extension EffectProducer {
6-
/// Wraps the emission of each element with SwiftUI's `withAnimation`.
7-
///
8-
/// ```swift
9-
/// case .buttonTapped:
10-
/// return .task {
11-
/// .activityResponse(await self.apiClient.fetchActivity())
12-
/// }
13-
/// .animation()
14-
/// ```
15-
///
16-
/// - Parameter animation: An animation.
6+
/// Wraps the emission of each element with SwiftUI's `withAnimation`.
7+
///
8+
/// ```swift
9+
/// case .buttonTapped:
10+
/// return .task {
11+
/// .activityResponse(await self.apiClient.fetchActivity())
12+
/// }
13+
/// .animation()
14+
/// ```
15+
///
16+
/// - Parameter animation: An animation.
1717
/// - Returns: An effect.
18-
public func animation(_ animation: Animation? = .default) -> Self {
19-
switch self.operation {
20-
case .none:
21-
return .none
18+
public func animation(_ animation: Animation? = .default) -> Self {
19+
self.transaction(Transaction(animation: animation))
20+
}
21+
22+
/// Wraps the emission of each element with SwiftUI's `withTransaction`.
23+
///
24+
/// ```swift
25+
/// case .buttonTapped:
26+
/// var transaction = Transaction(animation: .default)
27+
/// transaction.disablesAnimations = true
28+
/// return .task {
29+
/// .activityResponse(await self.apiClient.fetchActivity())
30+
/// }
31+
/// .transaction(transaction)
32+
/// ```
33+
///
34+
/// - Parameter transaction: A transaction.
35+
/// - Returns: A publisher.
36+
public func transaction(_ transaction: Transaction) -> Self {
37+
switch self.operation {
38+
case .none:
39+
return .none
2240
case let .producer(producer):
23-
return Self(
41+
return Self(
2442
operation: .producer(
2543
SignalProducer<Action, Failure> { observer, _ in
2644
producer.start { action in
2745
switch action {
2846
case let .value(value):
29-
withAnimation(animation) {
47+
withTransaction(transaction) {
3048
observer.send(value: value)
3149
}
3250
case .completed:
@@ -38,21 +56,21 @@
3856
}
3957
}
4058
}
41-
)
4259
)
43-
case let .run(priority, operation):
44-
return Self(
45-
operation: .run(priority) { send in
46-
await operation(
47-
Send { value in
48-
withAnimation(animation) {
49-
send(value)
50-
}
60+
)
61+
case let .run(priority, operation):
62+
return Self(
63+
operation: .run(priority) { send in
64+
await operation(
65+
Send { value in
66+
withTransaction(transaction) {
67+
send(value)
5168
}
52-
)
53-
}
54-
)
55-
}
69+
}
70+
)
71+
}
72+
)
5673
}
5774
}
75+
}
5876
#endif

Sources/ComposableArchitecture/ViewStore.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,19 @@ public final class ViewStore<ViewState, ViewAction> {
306306
/// - animation: An animation.
307307
@discardableResult
308308
public func send(_ action: ViewAction, animation: Animation?) -> ViewStoreTask {
309-
withAnimation(animation) {
309+
send(action, transaction: Transaction(animation: animation))
310+
}
311+
312+
/// Sends an action to the store with a given transaction.
313+
///
314+
/// See ``ViewStore/send(_:)`` for more info.
315+
///
316+
/// - Parameters:
317+
/// - action: An action.
318+
/// - transaction: A transaction.
319+
@discardableResult
320+
public func send(_ action: ViewAction, transaction: Transaction) -> ViewStoreTask {
321+
withTransaction(transaction) {
310322
self.send(action)
311323
}
312324
}

0 commit comments

Comments
 (0)