From e2ad598ae466e4dfe034be751796fd96a82cb37b Mon Sep 17 00:00:00 2001 From: Jeff Verkoeyen Date: Tue, 18 Apr 2017 14:20:10 -0400 Subject: [PATCH] Deprecate transitionController.dismisser and move the APIs into TransitionController. Summary: Also generally consolidating transition gesture recognizers into a single entity so that it's easier to add gesture recognizers to the transition. Reviewers: O2 Material Motion, O4 Material Apple platform reviewers, #material_motion, markwei Reviewed By: O2 Material Motion, O4 Material Apple platform reviewers, #material_motion, markwei Tags: #material_motion Differential Revision: http://codereview.cc/D3068 --- examples/ContextualTransitionExample.swift | 5 +- ...InteractivePushBackTransitionExample.swift | 4 +- src/transitions/TransitionContext.swift | 11 +--- src/transitions/TransitionController.swift | 63 ++++++++++++++++--- src/transitions/ViewControllerDismisser.swift | 15 +++-- 5 files changed, 72 insertions(+), 26 deletions(-) diff --git a/examples/ContextualTransitionExample.swift b/examples/ContextualTransitionExample.swift index 0767da9..eb26aa6 100644 --- a/examples/ContextualTransitionExample.swift +++ b/examples/ContextualTransitionExample.swift @@ -202,11 +202,10 @@ class PhotoAlbumViewController: UIViewController, UICollectionViewDataSource, UI view.addSubview(collectionView) - let dismisser = transitionController.dismisser - dismisser.disableSimultaneousRecognition(of: collectionView.panGestureRecognizer) + transitionController.disableSimultaneousRecognition(of: collectionView.panGestureRecognizer) for gesture in [UIPanGestureRecognizer(), UIPinchGestureRecognizer(), UIRotationGestureRecognizer()] { - dismisser.dismissWhenGestureRecognizerBegins(gesture) + transitionController.dismissWhenGestureRecognizerBegins(gesture) view.addGestureRecognizer(gesture) } } diff --git a/examples/InteractivePushBackTransitionExample.swift b/examples/InteractivePushBackTransitionExample.swift index 4ffaa6b..d21c66c 100644 --- a/examples/InteractivePushBackTransitionExample.swift +++ b/examples/InteractivePushBackTransitionExample.swift @@ -59,8 +59,8 @@ private class ModalViewController: UIViewController, UIGestureRecognizerDelegate view.addSubview(scrollView) let pan = UIPanGestureRecognizer() - pan.delegate = transitionController.dismisser.topEdgeDismisserDelegate(for: scrollView) - transitionController.dismisser.dismissWhenGestureRecognizerBegins(pan) + pan.delegate = transitionController.topEdgeDismisserDelegate(for: scrollView) + transitionController.dismissWhenGestureRecognizerBegins(pan) scrollView.panGestureRecognizer.require(toFail: pan) view.addGestureRecognizer(pan) } diff --git a/src/transitions/TransitionContext.swift b/src/transitions/TransitionContext.swift index 6917333..8664d59 100644 --- a/src/transitions/TransitionContext.swift +++ b/src/transitions/TransitionContext.swift @@ -85,11 +85,7 @@ public final class TransitionContext: NSObject { public let fore: UIViewController /** The set of gesture recognizers associated with this transition. */ - public var gestureRecognizers: Set { - get { - return dismisser.gestureRecognizers - } - } + public let gestureRecognizers: Set /** The runtime to which motion should be registered. */ fileprivate var runtime: MotionRuntime! @@ -100,12 +96,12 @@ public final class TransitionContext: NSObject { direction: TransitionDirection, back: UIViewController, fore: UIViewController, - dismisser: ViewControllerDismisser) { + gestureRecognizers: Set) { self.direction = createProperty("Transition.direction", withInitialValue: direction) self.initialDirection = direction self.back = back self.fore = fore - self.dismisser = dismisser + self.gestureRecognizers = gestureRecognizers self.window = TransitionTimeWindow(duration: TransitionContext.defaultDuration) // TODO: Create a Timeline. @@ -118,7 +114,6 @@ public final class TransitionContext: NSObject { fileprivate let initialDirection: TransitionDirection fileprivate var transition: Transition! fileprivate var context: UIViewControllerContextTransitioning! - fileprivate let dismisser: ViewControllerDismisser fileprivate var didRegisterTerminator = false } diff --git a/src/transitions/TransitionController.swift b/src/transitions/TransitionController.swift index d93b679..51906c9 100644 --- a/src/transitions/TransitionController.swift +++ b/src/transitions/TransitionController.swift @@ -69,14 +69,44 @@ public final class TransitionController { } /** - Gesture recognizers associated with a view controller dismisser will cause the associated view - controller to be dismissed when the gesture recognizers begin. + Start a dismiss transition when the given gesture recognizer enters its began or recognized + state. - Provided gesture recognizers will also be made available to the Transition instance via the - TransitionContext's gestureRecognizers property. + The provided gesture recognizer will be made available to the transition instance via the + TransitionContext's `gestureRecognizers` property. */ - public var dismisser: ViewControllerDismisser { - return _transitioningDelegate.dismisser + public func dismissWhenGestureRecognizerBegins(_ gestureRecognizer: UIGestureRecognizer) { + _transitioningDelegate.dismisser.dismissWhenGestureRecognizerBegins(gestureRecognizer) + } + + /** + Will not allow the provided gesture recognizer to recognize simultaneously with other gesture + recognizers. + + This method assumes that the provided gesture recognizer's delegate has been assigned to the + transition controller's gesture delegate. + */ + public func disableSimultaneousRecognition(of gestureRecognizer: UIGestureRecognizer) { + _transitioningDelegate.dismisser.disableSimultaneousRecognition(of: gestureRecognizer) + } + + /** + Returns a gesture recognizer delegate that will allow the gesture recognizer to begin only if the + provided scroll view is scrolled to the top of its content. + + The returned delegate implements gestureRecognizerShouldBegin. + */ + public func topEdgeDismisserDelegate(for scrollView: UIScrollView) -> UIGestureRecognizerDelegate { + return _transitioningDelegate.dismisser.topEdgeDismisserDelegate(for: scrollView) + } + + /** + The set of gesture recognizers that will be provided to the transition via the TransitionContext + instance. + */ + public var gestureRecognizers: Set { + set { _transitioningDelegate.gestureDelegate.gestureRecognizers = newValue } + get { return _transitioningDelegate.gestureDelegate.gestureRecognizers } } /** @@ -89,10 +119,25 @@ public final class TransitionController { return _transitioningDelegate } + /** + The gesture recognizer delegate managed by this controller. + */ + public var gestureDelegate: UIGestureRecognizerDelegate { + return _transitioningDelegate.gestureDelegate + } + init(viewController: UIViewController) { _transitioningDelegate = TransitioningDelegate(viewController: viewController) } + /** + Deprecated. Please use methods directly on the transitionController instead. + */ + @available(*, deprecated, message: "Please use methods directly on the transitionController instead.") + public var dismisser: ViewControllerDismisser { + return _transitioningDelegate.dismisser + } + fileprivate let _transitioningDelegate: TransitioningDelegate } @@ -100,7 +145,7 @@ private final class TransitioningDelegate: NSObject, UIViewControllerTransitioni init(viewController: UIViewController) { self.associatedViewController = viewController - self.dismisser = ViewControllerDismisser() + self.dismisser = ViewControllerDismisser(gestureDelegate: self.gestureDelegate) super.init() @@ -109,7 +154,9 @@ private final class TransitioningDelegate: NSObject, UIViewControllerTransitioni var ctx: TransitionContext? var transitionType: Transition.Type? + let dismisser: ViewControllerDismisser + let gestureDelegate = GestureDelegate() weak var associatedViewController: UIViewController? @@ -133,7 +180,7 @@ private final class TransitioningDelegate: NSObject, UIViewControllerTransitioni direction: direction, back: back, fore: fore, - dismisser: dismisser) + gestureRecognizers: gestureDelegate.gestureRecognizers) ctx?.delegate = self } } diff --git a/src/transitions/ViewControllerDismisser.swift b/src/transitions/ViewControllerDismisser.swift index 9a811e4..65b85fa 100644 --- a/src/transitions/ViewControllerDismisser.swift +++ b/src/transitions/ViewControllerDismisser.swift @@ -74,10 +74,15 @@ public final class ViewControllerDismisser { weak var delegate: ViewControllerDismisserDelegate? public var gestureRecognizers: Set { - return gestureDelegate.gestureRecognizers + set { gestureDelegate.gestureRecognizers = newValue } + get { return gestureDelegate.gestureRecognizers } } - private var gestureDelegate = GestureDelegate() + init(gestureDelegate: GestureDelegate) { + self.gestureDelegate = gestureDelegate + } + + private var gestureDelegate: GestureDelegate private var scrollViewTopEdgeDismisserDelegates: [ScrollViewTopEdgeDismisserDelegate] = [] } @@ -93,9 +98,9 @@ private final class ScrollViewTopEdgeDismisserDelegate: NSObject, UIGestureRecog weak var scrollView: UIScrollView? } -private final class GestureDelegate: NSObject, UIGestureRecognizerDelegate { - fileprivate var gestureRecognizers = Set() - fileprivate var soloGestureRecognizers = Set() +final class GestureDelegate: NSObject, UIGestureRecognizerDelegate { + var gestureRecognizers = Set() + var soloGestureRecognizers = Set() public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { if soloGestureRecognizers.contains(gestureRecognizer) || soloGestureRecognizers.contains(otherGestureRecognizer) {