How do I Disable the swipe gesture of UIPageViewCo

2019-01-04 07:58发布

In my case parent UIViewController contains UIPageViewController which contains UINavigationController which contains UIViewController. I want to add a swipe gesture to the last view controller, but swipes are handled as if they belong to page view controller. I tried to do this both programmatically and via xib but with no result.

So as I understand I can't achieve my goal until UIPageViewController handles its gestures. How to solve this issue?

13条回答
冷血范
2楼-- · 2019-01-04 07:58

The documented way to prevent the UIPageViewController from scrolling is to not assign the dataSource property. If you assign the data source it will move into 'gesture-based' navigation mode which is what you're trying to prevent.

Without a data source you manually provide view controllers when you want to with setViewControllers:direction:animated:completion method and it will move between view controllers on demand.

The above can be deduced from Apple's documentation of UIPageViewController (Overview, second paragraph):

To support gesture-based navigation, you must provide your view controllers using a data source object.

查看更多
贼婆χ
3楼-- · 2019-01-04 08:04

If you want your UIPageViewController to maintain it's ability to swipe, while allowing your content controls to use their features (Swipe to delete, etc), just turn off canCancelContentTouches in the UIPageViewController.

Put this in your UIPageViewController's viewDidLoad func. (Swift)

if let myView = view?.subviews.first as? UIScrollView {
    myView.canCancelContentTouches = false
}

The UIPageViewController has an auto-generated subview that handles the gestures. We can prevent these subviews from cancelling content gestures.

From...

Swipe to delete on a tableView that is inside a pageViewController

查看更多
Bombasti
4楼-- · 2019-01-04 08:06

Similar to @user3568340 answer

Swift 4

private var _enabled = true
    public var enabled:Bool {
        set {
            if _enabled != newValue {
                _enabled = newValue
                if _enabled {
                    dataSource = self
                }
                else{
                    dataSource = nil
                }
            }
        }
        get {
            return _enabled
        }
    }
查看更多
爷的心禁止访问
5楼-- · 2019-01-04 08:07

Edit: this answer works for page curl style only. Jessedc's answer is far better: works regardless of the style and relies on documented behavior.

UIPageViewController exposes its array of gesture recognizers, which you could use to disable them:

// myPageViewController is your UIPageViewController instance
for (UIGestureRecognizer *recognizer in myPageViewController.gestureRecognizers) {
    recognizer.enabled = NO;
}
查看更多
Rolldiameter
6楼-- · 2019-01-04 08:09

(Swift 4) You can remove gestureRecognizers of your pageViewController:

pageViewController.view.gestureRecognizers?.forEach({ (gesture) in
            view.removeGestureRecognizer(gesture)
        })

If you prefer in extension:

extension UIViewController{
    func removeGestureRecognizers(){
        view.gestureRecognizers?.forEach({ (gesture) in
            view.removeGestureRecognizer(gesture)
        })
    }
}

and pageViewController.removeGestureRecognizers

查看更多
该账号已被封号
7楼-- · 2019-01-04 08:10

I've been fighting this for a while now and thought I should post my solution, following on from Jessedc's answer; removing the PageViewController's datasource.

I added this to my PgeViewController class (linked to my page view controller in the storyboard, inherits both UIPageViewController and UIPageViewControllerDataSource):

static func enable(enable: Bool){
    let appDelegate  = UIApplication.sharedApplication().delegate as! AppDelegate
    let pageViewController = appDelegate.window!.rootViewController as! PgeViewController
    if (enable){
        pageViewController.dataSource = pageViewController
    }else{
        pageViewController.dataSource = nil
    }
}

This can then be called when each sub view appears (in this case to disable it);

override func viewDidAppear(animated: Bool) {
    PgeViewController.enable(false)
}

I hope this helps someone out, its not as clean as I would like it but doesn't feel too hacky etc.

EDIT: If someone wants to translate this into Objective-C please do :)

查看更多
登录 后发表回答