Disable Gesture to Pull Down Form/Page Sheet Modal Presentation

Disable gesture to pull down form/page sheet modal presentation

In general, you shouldn't try to disable the swipe to dismiss functionality, as users expect all form/page sheets to behave the same across all apps. Instead, you may want to consider using a full-screen presentation style. If you do want to use a sheet that can't be dismissed via swipe, set isModalInPresentation = true, but note this still allows the sheet to be pulled down vertically and it'll bounce back up upon releasing the touch. Check out the UIAdaptivePresentationControllerDelegate documentation to react when the user tries to dismiss it via swipe, among other actions.

If you have a scenario where your app's gesture or touch handling is impacted by the swipe to dismiss feature, I did receive some advice from an Apple engineer on how to fix that.

If you can prevent the system's pan gesture recognizer from beginning, this will prevent the gestural dismissal. A few ways to do this:

  1. If your canvas drawing is done with a gesture recognizer, such as your own UIGestureRecognizer subclass, enter the began phase before the sheet’s dismiss gesture does. If you recognize as quickly as UIPanGestureRecognizer, you will win, and the sheet’s dismiss gesture will be subverted.

  2. If your canvas drawing is done with a gesture recognizer, setup a dynamic failure requirement with -shouldBeRequiredToFailByGestureRecognizer: (or the related delegate method), where you return NO if the passed in gesture recognizer is a UIPanGestureRecognizer.

  3. If your canvas drawing is done with manual touch handling (e.g. touchesBegan:), override -gestureRecognizerShouldBegin on your touch handling view, and return NO if the passed in gesture recognizer is a UIPanGestureRecognizer.

With my setup #3 proved to work very well. This allows the user to swipe down anywhere outside of the drawing canvas to dismiss (like the nav bar), while allowing the user to draw without moving the sheet, just as one would expect.

I cannot recommend trying to find the gesture to disable it, as it seems to be rather dynamic and can reenable itself when switching between different size classes for example, and this could change in future releases.

Disable the interactive dismissal of presented view controller

Option 1:

viewController.isModalInPresentation = true

Disabled interactive dismissal

(Disabled interactive .pageSheet dismissal acts like this.)

  • Since the iOS 13, UIViewController contains a new property called isModalInPresentation which must be set to true to prevent the interactive dismissal.
  • It basically ignores events outside the view controller's bounds. Bear that in mind if you are using not only the automatic style but also presentation styles like .popover etc.
  • This property is false by default.

From the official docs: If true, UIKit ignores events outside the view controller's bounds and prevents the interactive dismissal of the view controller while it is onscreen.



Option 2:

func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
return false
}
  • Since the iOS 13, UIAdaptivePresentationControllerDelegate contains a new method called presentationControllerShouldDismiss.
  • This method is called only if the presented view controller is not dismissed programmatically and its isModalInPresentation property is set to false.

Tip: Don't forget to assign presentationController's delegate. But be aware, it is known that even just accessing the presentationController can cause a memory leak.

Disable gesture to pull down form/page sheet modal presentation

In general, you shouldn't try to disable the swipe to dismiss functionality, as users expect all form/page sheets to behave the same across all apps. Instead, you may want to consider using a full-screen presentation style. If you do want to use a sheet that can't be dismissed via swipe, set isModalInPresentation = true, but note this still allows the sheet to be pulled down vertically and it'll bounce back up upon releasing the touch. Check out the UIAdaptivePresentationControllerDelegate documentation to react when the user tries to dismiss it via swipe, among other actions.

If you have a scenario where your app's gesture or touch handling is impacted by the swipe to dismiss feature, I did receive some advice from an Apple engineer on how to fix that.

If you can prevent the system's pan gesture recognizer from beginning, this will prevent the gestural dismissal. A few ways to do this:

  1. If your canvas drawing is done with a gesture recognizer, such as your own UIGestureRecognizer subclass, enter the began phase before the sheet’s dismiss gesture does. If you recognize as quickly as UIPanGestureRecognizer, you will win, and the sheet’s dismiss gesture will be subverted.

  2. If your canvas drawing is done with a gesture recognizer, setup a dynamic failure requirement with -shouldBeRequiredToFailByGestureRecognizer: (or the related delegate method), where you return NO if the passed in gesture recognizer is a UIPanGestureRecognizer.

  3. If your canvas drawing is done with manual touch handling (e.g. touchesBegan:), override -gestureRecognizerShouldBegin on your touch handling view, and return NO if the passed in gesture recognizer is a UIPanGestureRecognizer.

With my setup #3 proved to work very well. This allows the user to swipe down anywhere outside of the drawing canvas to dismiss (like the nav bar), while allowing the user to draw without moving the sheet, just as one would expect.

I cannot recommend trying to find the gesture to disable it, as it seems to be rather dynamic and can reenable itself when switching between different size classes for example, and this could change in future releases.

How disable drag dismiss in UIViewController

You need disable your pan gesture to disable drag dismiss.

ios13 prevent pulling down on tableView which is scrolled to top from dismissing sheet style modally presented viewController

You can disable the pull-to-dismiss behavior by setting isModalInPresentation to true on your table view controller when the user begins dragging on the table view, and then reset it back to false when they stop dragging, like so:

class YourTableViewController: UITableViewController {
override func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
isModalInPresentation = true
}

override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
isModalInPresentation = false
}
}

Note that you'll still be able to slightly pull down your table view controller, but at least you won't be able to dismiss it entirely. And since the value is set back to false when dragging stops, you'll be able to dismiss by pulling down on the navigation bar.

Also, if you add a UIRefreshControl to your table view, it disables the pull-to-dismiss behavior when pulling down on the table view.



Related Topics



Leave a reply



Submit