diff --git a/PanModal/Animator/PanModalPresentationAnimator.swift b/PanModal/Animator/PanModalPresentationAnimator.swift index f7fbdd0e..7390e801 100644 --- a/PanModal/Animator/PanModalPresentationAnimator.swift +++ b/PanModal/Animator/PanModalPresentationAnimator.swift @@ -91,10 +91,11 @@ public class PanModalPresentationAnimator: NSObject { PanModalAnimator.animate({ panView.frame.origin.y = yPos - }, config: presentable) { [weak self] didComplete in + }, config: presentable) { [weak self] _ in // Calls viewDidAppear and viewDidDisappear fromVC.endAppearanceTransition() - transitionContext.completeTransition(didComplete) + // Regardless of animation canceling, complete transition + transitionContext.completeTransition(true) self?.feedbackGenerator = nil } } @@ -117,11 +118,12 @@ public class PanModalPresentationAnimator: NSObject { PanModalAnimator.animate({ panView.frame.origin.y = transitionContext.containerView.frame.height - }, config: presentable) { didComplete in + }, config: presentable) { _ in fromVC.view.removeFromSuperview() // Calls viewDidAppear and viewDidDisappear toVC.endAppearanceTransition() - transitionContext.completeTransition(didComplete) + // Regardless of animation canceling, complete transition + transitionContext.completeTransition(true) } } diff --git a/PanModal/Controller/PanModalPresentationController.swift b/PanModal/Controller/PanModalPresentationController.swift index 11fb2a6e..022af3e8 100644 --- a/PanModal/Controller/PanModalPresentationController.swift +++ b/PanModal/Controller/PanModalPresentationController.swift @@ -484,6 +484,28 @@ private extension PanModalPresentationController { return } + let transitionForPosition = { [weak self] in + guard let me = self else { return } + let shortFormYPosition = me.shortFormYPosition + let longFormYPosition = me.longFormYPosition + + /** + The `containerView.bounds.height` is used to determine + how close the presented view is to the bottom of the screen + */ + let position = me.nearest(to: me.presentedView.frame.minY, inValues: [containerView.bounds.height, shortFormYPosition, longFormYPosition]) + + if position == longFormYPosition { + me.transition(to: .longForm) + + } else if position == shortFormYPosition || me.presentable?.allowsDragToDismiss == false { + me.transition(to: .shortForm) + + } else { + me.presentedViewController.dismiss(animated: true) + } + } + switch recognizer.state { case .began, .changed: @@ -499,6 +521,13 @@ private extension PanModalPresentationController { presentable?.willTransition(to: .longForm) } + case .cancelled, + .failed: + /** + When gesture is cancelled, transition to nearest position. + */ + transitionForPosition() + default: /** @@ -527,22 +556,7 @@ private extension PanModalPresentationController { } } else { - - /** - The `containerView.bounds.height` is used to determine - how close the presented view is to the bottom of the screen - */ - let position = nearest(to: presentedView.frame.minY, inValues: [containerView.bounds.height, shortFormYPosition, longFormYPosition]) - - if position == longFormYPosition { - transition(to: .longForm) - - } else if position == shortFormYPosition || presentable?.allowsDragToDismiss == false { - transition(to: .shortForm) - - } else { - presentedViewController.dismiss(animated: true) - } + transitionForPosition() } } }