Skip to content

Commit d6c3af3

Browse files
authored
Improve AnyNavigationTransition internals (#23)
Specifically, model handlers as an enum instead of two optionals. This helps avoid awkward code paths.
1 parent 2991e78 commit d6c3af3

File tree

4 files changed

+35
-30
lines changed

4 files changed

+35
-30
lines changed

Sources/NavigationTransition/AnyNavigationTransition.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Animation
22
import UIKit
33

44
public struct AnyNavigationTransition {
5-
@_spi(package)public typealias Handler = (
5+
@_spi(package)public typealias TransientHandler = (
66
AnimatorTransientView,
77
AnimatorTransientView,
88
NavigationTransitionOperation,
@@ -15,21 +15,23 @@ public struct AnyNavigationTransition {
1515
UIViewControllerContextTransitioning
1616
) -> Void
1717

18+
@_spi(package)public enum Handler {
19+
case transient(TransientHandler)
20+
case primitive(PrimitiveHandler)
21+
}
22+
1823
@_spi(package)public let type: Any.Type
19-
@_spi(package)public let handler: Handler?
20-
@_spi(package)public let primitiveHandler: PrimitiveHandler?
24+
@_spi(package)public let handler: Handler
2125
@_spi(package)public var animation: Animation = .default
2226

2327
public init<T: NavigationTransition>(_ transition: T) {
2428
self.type = Swift.type(of: transition)
25-
self.handler = transition.transition(from:to:for:in:)
26-
self.primitiveHandler = nil
29+
self.handler = .transient(transition.transition(from:to:for:in:))
2730
}
2831

2932
public init<T: PrimitiveNavigationTransition>(_ transition: T) {
3033
self.type = Swift.type(of: transition)
31-
self.handler = nil
32-
self.primitiveHandler = transition.transition(with:for:in:)
34+
self.handler = .primitive(transition.transition(with:for:in:))
3335
}
3436
}
3537

Sources/NavigationTransition/Combined.swift

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@ extension AnyNavigationTransition {
22
/// Combines this transition with another, returning a new transition that is the result of both transitions
33
/// being applied.
44
public func combined(with other: Self) -> Self {
5-
guard let lhsHandler = self.handler, let rhsHandler = other.handler else {
5+
switch (self.handler, other.handler) {
6+
case (.transient(let lhsHandler), .transient(let rhsHandler)):
7+
return AnyNavigationTransition(
8+
Combined(Erased(handler: lhsHandler), Erased(handler: rhsHandler))
9+
)
10+
case (.transient, .primitive),
11+
(.primitive, .transient),
12+
(.primitive, .primitive):
613
runtimeWarn(
714
"""
8-
Combining primitive and non-primitive transitions via 'combine(with:)' is not allowed.
15+
Combining primitive and non-primitive or two primitive transitions via 'combine(with:)' is not allowed.
16+
17+
The left-hand side transition will be left unmodified and the right-hand side transition will be discarded.
918
"""
1019
)
1120
return self
1221
}
13-
return .init(
14-
Combined(Erased(handler: lhsHandler), Erased(handler: rhsHandler))
15-
)
1622
}
1723
}
1824

Sources/NavigationTransition/Erased.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// A type erased transition for internal use only.
22
struct Erased: NavigationTransition {
3-
private let handler: AnyNavigationTransition.Handler
3+
private let handler: AnyNavigationTransition.TransientHandler
44

5-
init(handler: @escaping AnyNavigationTransition.Handler) {
5+
init(handler: @escaping AnyNavigationTransition.TransientHandler) {
66
self.handler = handler
77
}
88

Sources/NavigationTransitions/NavigationTransitionDelegate.swift

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -65,43 +65,40 @@ final class NavigationTransitionAnimatorProvider: NSObject, UIViewControllerAnim
6565
if let cached = cachedAnimators[ObjectIdentifier(transitionContext)] {
6666
return cached
6767
}
68-
6968
let animator = UIViewPropertyAnimator(
7069
duration: transitionDuration(using: transitionContext),
7170
timingParameters: transition.animation.timingParameters
7271
)
72+
cachedAnimators[ObjectIdentifier(transitionContext)] = animator
7373

74-
// Handle NavigationTransition setup
75-
if let (fromView, toView) = transientViews(for: transition, animator: animator, context: transitionContext) {
76-
fromView.setUIViewProperties(to: \.initial)
77-
animator.addAnimations { fromView.setUIViewProperties(to: \.animation) }
78-
animator.addCompletion { _ in fromView.setUIViewProperties(to: \.completion) }
79-
80-
toView.setUIViewProperties(to: \.initial)
81-
animator.addAnimations { toView.setUIViewProperties(to: \.animation) }
82-
animator.addCompletion { _ in toView.setUIViewProperties(to: \.completion) }
83-
}
74+
switch transition.handler {
75+
case .transient(let handler):
76+
if let (fromView, toView) = transientViews(for: handler, animator: animator, context: transitionContext) {
77+
fromView.setUIViewProperties(to: \.initial)
78+
animator.addAnimations { fromView.setUIViewProperties(to: \.animation) }
79+
animator.addCompletion { _ in fromView.setUIViewProperties(to: \.completion) }
8480

85-
// Handle PrimitiveNavigationTransition setup
86-
if let handler = transition.primitiveHandler {
81+
toView.setUIViewProperties(to: \.initial)
82+
animator.addAnimations { toView.setUIViewProperties(to: \.animation) }
83+
animator.addCompletion { _ in toView.setUIViewProperties(to: \.completion) }
84+
}
85+
case .primitive(let handler):
8786
handler(animator, operation, transitionContext)
8887
}
8988

9089
animator.addCompletion { _ in
9190
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
9291
}
9392

94-
cachedAnimators[ObjectIdentifier(transitionContext)] = animator
9593
return animator
9694
}
9795

9896
private func transientViews(
99-
for transition: AnyNavigationTransition,
97+
for handler: AnyNavigationTransition.TransientHandler,
10098
animator: Animator,
10199
context: UIViewControllerContextTransitioning
102100
) -> (fromView: AnimatorTransientView, toView: AnimatorTransientView)? {
103101
guard
104-
let handler = transition.handler,
105102
let fromUIView = context.view(forKey: .from),
106103
let fromUIViewSnapshot = fromUIView.snapshotView(afterScreenUpdates: false),
107104
let toUIView = context.view(forKey: .to),

0 commit comments

Comments
 (0)