1
votes

I'm trying to assign the UIPanGestureRecognizer of a UIPageViewController to a different (custom) view, so that the pan gesture, for page switching, only works for a certain area of the screen. The code is basically the following:

let testView = UIView(frame: CGRect(x: 0, y:self.view.frame.height/2, width: 320, height: self.view.frame.height/2))
self.view.addSubview(testView)
for gr in self.pageViewController!.view.subviews[0].gestureRecognizers! {            
        if gr.isKindOfClass(UIPanGestureRecognizer) {
            testView.addGestureRecognizer(gr)
        }
}

The problem is that the "next" view controller is not immediately visible when doing the pan, on first pan it appears the current view controller (the first one) is the only one inside PageViewController, it's only after ending the pan and doing a second pan that the next view controller appears.

Note that without assigning the UIPanGesture to a different view, the PageViewController works as expected with the next view controller visible since first pan.

Why do I want to do this? I need to add a subview to the view controllers inside the PageViewController that does not "pan" the PageViewController when the user gestures on top of it.

1
Out of curiosity, why are you using a UIPanGestureRecognizer with a UIPageViewController? Maybe this is a noob question from my end, but with a UIPageViewController, there are delegate methods that allow you to turn the page or slide to the next view inside the UIPageViewController.impression7vx
Because I require that a subview of the view controllers inside the PageViewController does not Pan the the pageviewcontroller when the user interacts. An example of what I'm trying to do would be Apple's weather app. where you can pan a PageViewController between cities but also pan a subview (the current day's forecast for the city you're looking at) which does not pan the parent view. There is nothing in the UIPageViewController delegate methods that would allow to do this.ListenKid
I see, I see. Gimme a sec to answer. I am going to answer based off the weather app, cool?impression7vx
So why not add an additional pan gesture recognizer to the page view controller and then wire up your gesture recognizer to the page view controller's gesture recognizer as a "must fail". It's been a while since I looked at this, but there is a built-in mechanism where a gesture recognizer doesn't fire until another one fails.Duncan C
Tried that, the problem with adding another gesture recognizer that requires the PageViewController gesture recognizer to fail is that the gestures don't "pass" to the view below, so I'm not able to interact with the subview with gestures.ListenKid

1 Answers

0
votes

UIPageViewController

class PageController:UIPageViewController {

    let viewControllers:[UIViewController] = [MyController(), MyController(), MyController()]

    override init(transitionStyle style: UIPageViewControllerTransitionStyle, navigationOrientation: UIPageViewControllerNavigationOrientation, options: [String : AnyObject]?) {
super.init(transitionStyle: .Scroll, navigationOrientation: .Horizontal, options: options)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        if let firstVC = controllers.first {
            setViewControllers([firstVC], direction.Forward, animated: true, completion:nil)
        }    
    } 

    func pageViewController(pageViewController: UIPageViewController,
viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.indexOf(viewController) else {
            return nil
        }

        let previousIndex = viewControllerIndex - 1

        guard previousIndex >= 0 else {
            return nil
        }

        guard orderedViewControllers.count > previousIndex else {
            return nil
        }

        return orderedViewControllers[previousIndex]
     }

    func pageViewController(pageViewController: UIPageViewController,
viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        guard let viewControllerIndex = orderedViewControllers.indexOf(viewController) else {
            return nil
        }

        let nextIndex = viewControllerIndex + 1
        let orderedViewControllersCount = orderedViewControllers.count

        guard orderedViewControllersCount != nextIndex else {
            return nil
        }  

        guard orderedViewControllersCount > nextIndex else {
            return nil
        }

        return orderedViewControllers[nextIndex]
    }

 }

View

class SmallView:UIView {
    //Since yours is not a ScrollView I changed to a view. You can add the Pan Gesture here. 
     var colors:[UIColor] = [UIColor.redColor(), UIColor.blueColor(), UIColor.blackColor()]

     convenience init(frame: CGRect, x:Int) {
         self.init()
         self.frame = frame
         self.backgroundColor = colors[x]

         setupGesture()
     }

     func setupGesture() {
         let pan = UIPanGestureRecognizer(target: self, action: #selector(SmallView.action))
     }
     func action(gesture:UIPanGestureRecognizer) {
         print("gesture = ", gesture)
     }
}

MyController

class MyController:UIViewController {

    override func viewDidLoad() {
        ......
        let view = SmallView(frame:CGRect(//some frame here))
        self.view.addSubview(view)
}