title: Drag to dismiss a UIPresentationController
body: <p>I have made a UIPresentationController that fits any view controller and shows up on half of the screen using this <a href="https://www.raywenderlich.com/3636807-uipresentationcontroller-tutorial-getting-started#toc-anchor-012" rel="nofollow noreferrer">tutorial</a>. Now I would love to add drag to dismiss to this. I'm trying to have the drag feel natural and responsive like the drag experience for &quot;Top Stories&quot; on the Apple iOS 13 stocks app. I thought the iOS 13 modal drag to dismiss would get carried over but it doesn't to this controller but it doesn't.</p>
  <p>Every bit of code and tutorial I found had a bad dragging experience. Does anyone know how to do this? I've been trying / searching for the past week. Thank you in advance</p>
  <p>Here's my code for the presentation controller</p>
  <pre><code>class SlideUpPresentationController: UIPresentationController {
      // MARK: - Variables
      private var dimmingView: UIView!
      
      //MARK: - View functions
      override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
          super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
          setupDimmingView()
      }
      
      override func containerViewWillLayoutSubviews() {
        presentedView?.frame = frameOfPresentedViewInContainerView
      }
      
      override var frameOfPresentedViewInContainerView: CGRect {
          guard let container = containerView else { return super.frameOfPresentedViewInContainerView }
          let width = container.bounds.size.width
          let height : CGFloat = 300.0
          
          return CGRect(x: 0, y: container.bounds.size.height - height, width: width, height: height)
      }
      
      override func presentationTransitionWillBegin() {
          guard let dimmingView = dimmingView else { return }
          
          containerView?.insertSubview(dimmingView, at: 0)
        
        NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: &quot;V:|[dimmingView]|&quot;,
                                                                   options: [],
                                                                   metrics: nil,
                                                                   views: [&quot;dimmingView&quot;: dimmingView]))
        
        NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: &quot;H:|[dimmingView]|&quot;,
                                                                   options: [],
                                                                   metrics: nil,
                                                                   views: [&quot;dimmingView&quot;: dimmingView]))
        
        guard let coordinator = presentedViewController.transitionCoordinator else {
          dimmingView.alpha = 1.0
          return
        }
        
        coordinator.animate(alongsideTransition: { _ in
          self.dimmingView.alpha = 1.0
        })
      }
      
      override func dismissalTransitionWillBegin() {
        guard let coordinator = presentedViewController.transitionCoordinator else {
          dimmingView.alpha = 0.0
          return
        }
        
        coordinator.animate(alongsideTransition: { _ in
          self.dimmingView.alpha = 0.0
        })
      }
      
      func setupDimmingView() {
        dimmingView = UIView()
        dimmingView.translatesAutoresizingMaskIntoConstraints = false
        dimmingView.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
        dimmingView.alpha = 0.0
        
        let recognizer = UITapGestureRecognizer(target: self,
                                                action: #selector(handleTap(recognizer:)))
        dimmingView.addGestureRecognizer(recognizer)
      }
      
      @objc func handleTap(recognizer: UITapGestureRecognizer) {
        presentingViewController.dismiss(animated: true)
      }
  }
  </code></pre>