如何从 UIPageViewController 中的视图控制器返回上一个 VC 或下一个 VC?

Posted

技术标签:

【中文标题】如何从 UIPageViewController 中的视图控制器返回上一个 VC 或下一个 VC?【英文标题】:how to be back to previous VC or next VC from a view controller inside UIPageViewController? 【发布时间】:2019-06-13 00:25:36 【问题描述】:

我有 3 个由 UIPageViewController 控制的视图控制器,如下图所示

https://i.stack.imgur.com/9Lqoj.png

如果我滑动屏幕,它会从 RedVC 移动到 BlueVC 和 YellowVC。

我想在 BlueVC 中制作下一个按钮和返回按钮。因此,如果用户按下后退按钮,它将转到 RedVC,如果用户按下下一步按钮,它将转到 YellowVC。该怎么做?

这是我在根页面视图控制器中的代码:

import UIKit

class RootPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate 

    lazy var viewControllerList : [UIViewController] = 
        let storyBoard = UIStoryboard(name: "Main", bundle: nil)

        let redVC = storyBoard.instantiateViewController(withIdentifier: "redVC")
        let blueVC = storyBoard.instantiateViewController(withIdentifier: "blueVC")
        let yellowVC = storyBoard.instantiateViewController(withIdentifier: "yellowVC")

        return [redVC,blueVC,yellowVC]
    () 


    // to add dot indicator
    var pageControl = UIPageControl()




    override func viewDidLoad() 
        super.viewDidLoad()


        self.dataSource = self
        self.delegate = self

        configurePageControl()
        turnIntoPage()

    




    func turnIntoPage() 
        // set view controllers to be pages

        if let firstViewController = viewControllerList.first 
            // if so then set the direction
            self.setViewControllers([firstViewController], direction: .forward, animated: true, completion: nil)
        
    




    // MARK: - Page View Controller Data Source functions
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? 

        // a method that will handle view controller before current view controller

        // make precaution , if the lodic is wrong then return nil (prevent index out of logic)
        guard let vcIndex = viewControllerList.index(of: viewController) else  return nil
        let previousIndex = vcIndex - 1
        guard previousIndex >= 0 else  return nil
        guard viewControllerList.count > previousIndex else return nil


        // return the value
        return viewControllerList[previousIndex]
    


    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? 

        // a method that will handle view controller after current view controller

        // make precaution , if the lodic is wrong then return nil (prevent index out of logic)
        guard let vcIndex = viewControllerList.index(of: viewController) else  return nil
        let nextIndex = vcIndex + 1
        guard viewControllerList.count != nextIndex else return nil
        guard viewControllerList.count > nextIndex else return nil

         // return the value
        return viewControllerList[nextIndex]


    




     // to add dot indicator


    // MARK: Page View Controller Delegate functions
    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) 
        let pageContentViewController = pageViewController.viewControllers![0]
        self.pageControl.currentPage = viewControllerList.index(of: pageContentViewController)!
    


    func configurePageControl() 

        // The total number of pages that are available is based on how many available colors we have.
        pageControl = UIPageControl(frame: CGRect(x: 0,y: UIScreen.main.bounds.maxY - 50,width: UIScreen.main.bounds.width,height: 50))
        self.pageControl.numberOfPages = viewControllerList.count
        self.pageControl.currentPage = 0
        self.pageControl.tintColor = UIColor.black
        self.pageControl.pageIndicatorTintColor = UIColor.white
        self.pageControl.currentPageIndicatorTintColor = UIColor.black
        self.view.addSubview(pageControl)
    





【问题讨论】:

【参考方案1】:

因此,在您的RootPageViewController 中,您可以有一个使用setViewControllers 的函数。

setViewControllers 被描述为:

// 设置可见的视图控制器,可选地带有动画。大批 应该只包括在 动画已经完成。 // 对于过渡样式 'UIPageViewControllerTransitionStylePageCurl',如果 'doubleSided' 是 'YES' 并且脊椎位置不是 'UIPageViewControllerSpineLocationMid',必须有两个视图控制器 包括在内,因为后者的视图控制器被用作背面。

所以让我们尝试创建一个Next 函数。

func next() 
    let vcs = self.viewControllerList
    //or self.viewControllers
    let currentPage = self.pageControl.currentPage
    let nextPage = currentPage + 1

    if nextPage < vcs.count 
        let nextVC = vcs[nextPage]
        self.setViewControllers([nextVC], direction: .forward, animated: true)  _ in
            self.pageControl.currentPage = nextPage
        
    

如您所见,我们从您在代码中创建的vcs 安全地获取了一个viewController,其中包含所有页面。在我们得到下一个 viewController 之后,如果有的话,我们使用setViewControllers。为了让它变得更好,我们设置了 pageControlcurrentPage 来判断 pageController 底部的哪个圆圈要着色。

然后从您的BlueVC 获取您的pageController 的引用。如何?通过访问self.parent 并将其转换为您的RootPageViewController。像这样:

@IBAction func next(_ sender: Any) 
    if let parentVC = self.parent as? RootPageViewController 
        parentVC.next()
    

现在,您的任务是实现previous 函数。

【讨论】:

以上是关于如何从 UIPageViewController 中的视图控制器返回上一个 VC 或下一个 VC?的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从 UIPageViewController 传递到它的“子视图”之一?

如何从 UIPageViewController 中的视图控制器返回上一个 VC 或下一个 VC?

从 UIPageViewController 中移除页面指示器

如何在 UIPageViewController 中的两个 ViewController 之间传递数据

如何在 UIPageViewController 上禁用多点触控?

滑动最后一个视图控制器后,如何关闭/弹出 UIPageViewController?