         
     }
     
-    func finishWithTranslation(translation: CGPoint, velocity: CGPoint, completion: () -> Void) {
+    func finishWithTranslation(_ translation: CGPoint, velocity: CGPoint, completion: @escaping () -> Void) {
         
         guard let transitionContext = self.activeContext,
-            container = transitionContext.containerView(),
-            fromView = transitionContext.viewForKey(UITransitionContextFromViewKey),
-            toView = transitionContext.viewForKey(UITransitionContextToViewKey) else {
+            let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from),
+            let toView = transitionContext.view(forKey: UITransitionContextViewKey.to) else {
                 return
         }
         
+        let container = transitionContext.containerView
+        
         let maxDistance = container.bounds.size.width
-        let duration: NSTimeInterval
+        let duration: TimeInterval
 
         // Like a push mower, this gesture completion feels more
         // comfortable with a little added velocity.

use a different class for that purpose. Just forward the relevant delegate
methods to your sloppy swiping instance.
*/
class JTSSloppySwiping: NSObject {
    
    init(navigationController: UINavigationController) {
        self.interactivePopAnimator = InteractivePopAnimator()
        self.popRecognizer = UIPanGestureRecognizer()
        self.navigationController = navigationController
        super.init()
        self.popRecognizer.addTarget(self, action: "popRecognizerPanned:")
        navigationController.view.addGestureRecognizer(self.popRecognizer)
    }
    
    // MARK: Private
    
    private weak var navigationController: UINavigationController?
    private var isInteractivelyPopping: Bool = false
    private var interactivePopAnimator: InteractivePopAnimator
    private let popRecognizer: UIPanGestureRecognizer

    private var isAnimatingANonInteractiveTransition: Bool = false {
        didSet {
            self.popRecognizer.enabled = !self.isAnimatingANonInteractiveTransition
        }
    }
    
    @objc private func popRecognizerPanned(recognizer: UIPanGestureRecognizer) {
        
        guard let navigationController = self.navigationController else {
            return

    
}

private let defaultCancelPopDuration: TimeInterval = 0.16
private let maxBackViewTranslationPercentage: CGFloat = 0.30
private let minimumDismissalPercentage: CGFloat = 0.5
private let minimumThresholdVelocity: CGFloat = 100.0

private class InteractivePopAnimator: NSObject, UIViewControllerAnimatedTransitioning, UIViewControllerInteractiveTransitioning {
    
    var translation: CGPoint = CGPoint.zero {
        didSet {
            self.updateViewsWithTranslation(translation)
        }
    }
    
    fileprivate var activeContext: UIViewControllerContextTransitioning? = nil
    fileprivate var activeDuration: TimeInterval? = nil
    
    fileprivate let backOverlayView: UIView = {
        let backOverlayView = UIView(frame: CGRect.zero)
        backOverlayView.backgroundColor = UIColor(white: 0.0, alpha: 0.1)
        backOverlayView.alpha = 1.0
        return backOverlayView
        }()
    
    fileprivate let frontContainerView: FrontContainerView = {
        return FrontContainerView(frame: CGRect.zero)
    }()
    
    // MARK: UIViewControllerAnimatedTransitioning
    
    @objc func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        if let duration = self.activeDuration {
            return duration
        }
        return 0
    }
    
    @objc func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        fatalError("this class should not be used for non-interactive transitions")
    }
    
    // MARK: UIViewControllerInteractiveTransitioning
    
    @objc func startInteractiveTransition(_ transitionContext: UIViewControllerContextTransitioning) {
        self.activeContext = transitionContext
        self.prepForPop()
    }
