在页面视图控制器 (Swift) 中更改 VC 的索引

Change index of VC in page view controller (Swift)

使用以下代码,我将一系列视图控制器嵌入到我正在滑动的页面视图控制器中。我只是找不到通过按下条形按钮来切换到另一个视图控制器的方法。我打算为每个视图控制器中的每个条形按钮图标编写一个单独的函数。

class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    private var pages: [UIViewController]!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.dataSource = self
        self.delegate = self

        self.pages = [
            self.storyboard!.instantiateViewControllerWithIdentifier("FirstNav") as! UINavigationController,
            self.storyboard!.instantiateViewControllerWithIdentifier("SecondNav") as! UINavigationController,
            self.storyboard!.instantiateViewControllerWithIdentifier("ThirdNav") as! UINavigationController,
            self.storyboard!.instantiateViewControllerWithIdentifier("FourthNav") as! UINavigationController
        ]

        let startingViewController = self.pages.first! as UIViewController
        self.setViewControllers([startingViewController], direction: .Forward, animated: false, completion: nil)
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        let index = (self.pages as NSArray).indexOfObject(viewController)

        // if currently displaying last view controller, return nil to indicate that there is no next view controller
        return (index == self.pages.count - 1 ? nil : self.pages[index + 1])
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        let index = (self.pages as NSArray).indexOfObject(viewController)

        // if currently displaying first view controller, return nil to indicate that there is no previous view controller
        return (index == 0 ? nil : self.pages[index - 1])
    }

}

是否每个控制器都需要嵌入一个UINavigationController?您可以让 UINavigationController 嵌入一个 UIViewController,该视图控制器引用 pageviewcontrollerbarButtonItem,当 barButtonItem 被点击时触发一个动作告诉 pageviewcontroller 更改索引。

或者如果你想按照你当前的行动计划,即每个 UINavigationController 中的 barButtonItem,写一个带有委托方法的协议 didSelectBarButtonAtIndex 之类的,然后给每个 UINavigationController 一个代表 属性,让 pageviewcontroller 遵守协议并成为每个导航控制器的代表。然后当一个条形按钮被点击时,调用委托方法,这应该使页面控制器改变它的索引。

PageViewController 的实现更改为以下内容(我对您已经实现的方法进行了一些更改,并添加了一个新的实例方法。)

class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    private var pages: [UINavigationController]!

    private var currentPageIndex: Int!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.dataSource = self
        self.delegate = self

        self.pages = [
            self.storyboard!.instantiateViewControllerWithIdentifier("FirstNav") as! UINavigationController,
            self.storyboard!.instantiateViewControllerWithIdentifier("SecondNav") as! UINavigationController,
            self.storyboard!.instantiateViewControllerWithIdentifier("ThirdNav") as! UINavigationController,
            self.storyboard!.instantiateViewControllerWithIdentifier("FourthNav") as! UINavigationController
        ]

        (self.pages[0].topViewController as! FirstViewController).parentPageViewController = self
        (self.pages[1].topViewController as! SecondViewController).parentPageViewController = self
        (self.pages[2].topViewController as! ThirdViewController).parentPageViewController = self
        (self.pages[3].topViewController as! FourthViewController).parentPageViewController = self

        self.currentPageIndex = 0
        let startingViewController = self.pages.first! as UINavigationController
        self.setViewControllers([startingViewController], direction: .Forward, animated: false, completion: nil)
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        let index = (self.pages as NSArray).indexOfObject(viewController)
        self.currentPageIndex = index

        // if currently displaying last view controller, return nil to indicate that there is no next view controller
        return (self.currentPageIndex == self.pages.count - 1 ? nil : self.pages[self.currentPageIndex + 1])
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        let index = (self.pages as NSArray).indexOfObject(viewController)
        self.currentPageIndex = index

        // if currently displaying first view controller, return nil to indicate that there is no previous view controller
        return (index == 0 ? nil : self.pages[index - 1])
    }



    func displayPageForIndex(index: Int, animated: Bool = true) {
        assert(index >= 0 && index < self.pages.count, "Error: Attempting to display a page for an out of bounds index")

        // nop if index == self.currentPageIndex
        if self.currentPageIndex == index { return }

        if index < self.currentPageIndex {
            self.setViewControllers([self.pages[index]], direction: .Reverse, animated: true, completion: nil)
        } else if index > self.currentPageIndex {
            self.setViewControllers([self.pages[index]], direction: .Forward, animated: true, completion: nil)
        }

        self.currentPageIndex = index
    }

}

现在,在您的每个子视图控制器中,添加两段代码:

  1. 维护对父 PageViewController 实例的弱引用的 属性。

    weak var parentPageViewController: PageViewController!
    
  2. 一个 IBAction,您可以将每个栏按钮项目连接到它。您可能需要根据情节提要的设置更改此方法的主体。

    @IBAction func barButtonTapped(sender: UIBarButtonItem) {
    
        var newIndex = -1
    
        switch sender.title! {
        case "First":
            newIndex = 0
        case "Second":
            newIndex = 1
        case "Third":
            newIndex = 2
        case "Fourth":
            newIndex = 3
        default: break
        }
    
        self.parentPageViewController.displayPageForIndex(newIndex)
    }