iOS Swift: UIPageViewController - Turning page programmatically

后端 未结 6 823
我寻月下人不归
我寻月下人不归 2020-12-13 19:35

I have a UIPageViewController, which works fine when we swipe left or right to turn pages.

class ViewController: UIViewController, UIPageViewControllerDataSou         


        
相关标签:
6条回答
  • 2020-12-13 19:41

    Use this funtion and set the transition style for the animation you want.

    enter image description here

    enter image description here

    0 讨论(0)
  • 2020-12-13 19:50

    There's generally no need to fiddle around with page indexes and what not. Chances are you are already implementing a dataSource: UIPageViewControllerDataSource, which has all of what you need to get a previous or next ViewController to display.

    Swift 5 Example:

    extension UIPageViewController {
    
        func goToNextPage() {
           guard let currentViewController = self.viewControllers?.first else { return }
           guard let nextViewController = dataSource?.pageViewController( self, viewControllerAfter: currentViewController ) else { return }
           setViewControllers([nextViewController], direction: .forward, animated: false, completion: nil)
        }
    
        func goToPreviousPage() {
           guard let currentViewController = self.viewControllers?.first else { return }
           guard let previousViewController = dataSource?.pageViewController( self, viewControllerBefore: currentViewController ) else { return }
           setViewControllers([previousViewController], direction: .reverse, animated: false, completion: nil)
        }
    
    }
    

    This way you're guaranteed that the pages you're transitioning to are exactly what the PageViewController's built in gestures would trigger.

    0 讨论(0)
  • 2020-12-13 19:50

    Here is the swift 4 implementation with the delegates as well.

    Since I also use the UIPageViewControllerDelegate, and the delegate methods weren't called with most of the setViewController solutions.

    Thanks to Andrew Duncan's for his comment about the delegate.

    // Functions for clicking next and previous in the navbar, Updated for swift 4
    @objc func toNextArticle(){
        guard let currentViewController = self.viewControllers?.first else { return }
    
        guard let nextViewController = dataSource?.pageViewController( self, viewControllerAfter: currentViewController ) else { return }
    
        // Has to be set like this, since else the delgates for the buttons won't work
        setViewControllers([nextViewController], direction: .forward, animated: true, completion: { completed in self.delegate?.pageViewController?(self, didFinishAnimating: true, previousViewControllers: [], transitionCompleted: completed) })
    }
    
    @objc func toPreviousArticle(){
        guard let currentViewController = self.viewControllers?.first else { return }
    
        guard let previousViewController = dataSource?.pageViewController( self, viewControllerBefore: currentViewController ) else { return }
    
        // Has to be set like this, since else the delgates for the buttons won't work
        setViewControllers([previousViewController], direction: .reverse, animated: true, completion:{ completed in self.delegate?.pageViewController?(self, didFinishAnimating: true, previousViewControllers: [], transitionCompleted: completed) })
    }
    
    0 讨论(0)
  • 2020-12-13 19:55

    Here is a swift implementation of this:

    private func slideToPage(index: Int, completion: (() -> Void)?) {
        let count = //Function to get number of viewControllers
        if index < count {
            if index > currentPageIndex {
                if let vc = viewControllerAtIndex(index) {
                    self.pageViewController.setViewControllers([vc], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: { (complete) -> Void in
                        self.currentPageIndex = index
                        completion?()
                    })
                }
            } else if index < currentPageIndex {
                if let vc = viewControllerAtIndex(index) {
                    self.pageViewController.setViewControllers([vc], direction: UIPageViewControllerNavigationDirection.Reverse, animated: true, completion: { (complete) -> Void in
                        self.currentPageIndex = index
                        completion?()
                    })
                }
            }
        }
    }
    

    viewControllerAtIndex(index: Int) -> UIViewController? is my own function to get the correct view controller to swipe to.

    0 讨论(0)
  • 2020-12-13 19:56

    The Swift 3 version of SuitedSloth's answer (with a small tweak to the animated parameter as I needed it to be animated by default, but still taking a parameter in the function) in case anyone needs it:

    extension UIPageViewController {
    
        func goToNextPage(animated: Bool = true) {
            guard let currentViewController = self.viewControllers?.first else { return }
            guard let nextViewController = dataSource?.pageViewController(self, viewControllerAfter: currentViewController) else { return }
            setViewControllers([nextViewController], direction: .forward, animated: animated, completion: nil)
        }
    
        func goToPreviousPage(animated: Bool = true) {
            guard let currentViewController = self.viewControllers?.first else { return }
            guard let previousViewController = dataSource?.pageViewController(self, viewControllerBefore: currentViewController) else { return }
            setViewControllers([previousViewController], direction: .reverse, animated: animated, completion: nil)
        }
    
    }
    
    0 讨论(0)
  • 2020-12-13 19:56

    Just leaving this out here incase any one wants to use a defined protocol to navigate around and change view controllers programatically.

    @objc protocol AppWalkThroughDelegate {
      @objc optional func goNextPage(forwardTo position: Int)
      @objc optional func goPreviousPage(fowardTo position: Int)
    }
    

    Use the above protocol and confirm to root UIPageViewController to manage navigation between view controllers.

    Example below:

    class AppWalkThroughViewController: UIPageViewController, UIPageViewControllerDataSource, AppWalkThroughDelegate {
    
        // Add list of view controllers you want to load
    
        var viewControllerList : [UIViewControllers] = {
           let firstViewController = FirstViewController()
           let secondViewController = SecondViewController() 
           // Assign root view controller as first responder
           secondViewController.delegate = self  
    
           let thirdViewController = ThirdViewController() 
    
        }
    
        override func viewDidLoad() {
           super.viewDidLoad()
           self.dataSource = self
        }
    
        // Navigate to next page 
        func goNextPage(fowardTo position: Int) {
           let viewController = self.viewControllerList[position]
           setViewControllers([viewController], direction: 
           UIPageViewControllerNavigationDirection.forward, animated: true, completion: nil)
        }
    
        }
    

    Once achieved all that, child view controllers that need to make UIPageViewController move to next or previous page can use AppWalkThroughDelegate methods by passing a specific number onto delegate property.

    Example below: Delegate method invoked once button pressed

        class SecondViewController: UIViewController {
    
            var delegate: AppWalkThroughDelegate!
    
            override func viewDidLoad() {
               super.viewDidLoad()
               self.dataSource = self
            }
    
             @IBAction func goNextPage(_ sender: Any) {
                // Can be any number but not outside viewControllerList bounds 
                delegate.goNextPage!(fowardTo: 2)
             }
        }
    
    0 讨论(0)
提交回复
热议问题