使用Swift和多个视图控制器的UIPageViewController

18

我正在尝试在Swift应用程序中利用UIPageViewController,其中包含多个视图控制器。 我的故事板上有两个视图控制器(firstViewControllersecondViewController),它们都嵌入了自己的导航控制器。 它们具有故事板标识符“FirstViewController”和“SecondViewController”。 我的故事板上还有一个页面视图控制器,带有identifierPageView控制器,并将导航设置为水平,转换样式设置为滚动。 FirstViewController是应用程序的根视图控制器。

我希望firstViewController成为页面视图控制器的第一页,因此我编写了以下代码:

import Foundation
import UIKit

class FirsttViewController: UITableViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate  {

    override func viewDidLoad() {

        let pageViewController: PageViewController = self.storyboard.instantiateViewControllerWithIdentifier("PageViewController") as PageViewController

        pageViewController.delegate = self

        var viewControllers: [UIViewController] = [self]

        pageViewController.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
        pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)

        self.addChildViewController(pageViewController)
        self.view.addSubview(pageViewController.view)
        pageViewController.didMoveToParentViewController(self)


    }
    func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController! {


        let secondViewController: SecondViewController = self.storyboard.instantiateViewControllerWithIdentifier("SecondViewController") as SecondViewController


        return secondViewController
    }

    func pageViewController(pageViewController: UIPageViewController!, viewControllerBeforeViewController viewController: UIViewController!) -> UIViewController! {

        return nil
    }

    func presentationCountForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return 2
    }

    func presentationIndexForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return 0
    }
}

SecondViewController的文件看起来像这样:

import Foundation
import UIKit

class SecondViewController: UITableViewController, UIPageViewControllerDataSource {

    func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController! {

        return nil
    }

    func pageViewController(pageViewController: UIPageViewController!, viewControllerBeforeViewController viewController: UIViewController!) -> UIViewController! {

        let firstViewController: FirstViewController = self.storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as FirstViewController
        return firstViewController
    }

}

然而,当我运行我的应用程序时,似乎没有页面视图控制器。它只显示firstViewController,没有标点、页码等功能。有人知道是什么问题吗?我找到了一些Objective-C教程,但它们都涵盖了使用一个视图控制器来处理所有页面,并且有一个不在pageView中的根视图控制器,所以它们没有太大的帮助。我曾希望它会像使用tabBarController那样,你只需点击并拖动到视图控制器,但可惜这并不是这种情况。就像我说的,我以前没有使用过其中任何一个,所以我有点迷失。

更新:

按照iiFreeman的建议,我对UIPageViewController进行了子类化,并将其作为我的storyboard文件中的根。以下是该子类:

import Foundation
import UIKit
class PageViewController: UIPageViewController {

    override func viewDidLoad() {

        let startingViewController = self.storyboard.instantiateViewControllerWithIdentifier("FirstViewController") as FirstViewController

        self.dataSource = startingViewController
        var viewControllers: [UIViewController] = [startingViewController]

        self.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)



    }

}
然而,现在该应用程序只停留在黑屏上,并最终使 Xcode 与模拟器失去连接。我不太确定出了什么问题。

这里有一个不错的代码库: https://github.com/goktugyil/EZSwipeController - Esqarrouth
3个回答

33

好的,我已经弄清楚了。因为我需要页面视图控制器成为根并处理所有内容,所以我按照iiFreeman建议的方法将其子类化为UIPageViewController并遵守委托和数据源协议。然后我在viewDidLoad中设置了控制器,并实现了委托和数据源方法。我添加了一个属性来存储故事板标识符的数组,以及一个用于跟踪该数组当前索引的属性。我还添加了一个帮助方法,以便根据索引返回正确的视图控制器。由于我的tableViewController都嵌套在导航控制器中,我意识到我的页面视图控制器实际上需要显示导航控制器而不是tableView控制器。以下是我的实现:

import Foundation
import UIKit

class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    var index = 0
    var identifiers: NSArray = ["FirstNavigationController", "SecondNavigationController"]
    override func viewDidLoad() {

        self.dataSource = self
        self.delegate = self

        let startingViewController = self.viewControllerAtIndex(self.index)
        let viewControllers: NSArray = [startingViewController]
        self.setViewControllers(viewControllers, direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)



    }

    func viewControllerAtIndex(index: Int) -> UINavigationController! {

        //first view controller = firstViewControllers navigation controller
        if index == 0 {

            return self.storyboard.instantiateViewControllerWithIdentifier("FirstNavigationController") as UINavigationController

        }

        //second view controller = secondViewController's navigation controller
        if index == 1 {

            return self.storyboard.instantiateViewControllerWithIdentifier("SecondNavigationController") as UINavigationController
        }

        return nil
    }
    func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController! {

        let identifier = viewController.restorationIdentifier
        let index = self.identifiers.indexOfObject(identifier)

        //if the index is the end of the array, return nil since we dont want a view controller after the last one
        if index == identifiers.count - 1 {

            return nil
        }

        //increment the index to get the viewController after the current index
        self.index = self.index + 1
        return self.viewControllerAtIndex(self.index)

    }

    func pageViewController(pageViewController: UIPageViewController!, viewControllerBeforeViewController viewController: UIViewController!) -> UIViewController! {

        let identifier = viewController.restorationIdentifier
        let index = self.identifiers.indexOfObject(identifier)

        //if the index is 0, return nil since we dont want a view controller before the first one
        if index == 0 {

            return nil
        }

        //decrement the index to get the viewController before the current one
        self.index = self.index - 1
        return self.viewControllerAtIndex(self.index)

    }


    func presentationCountForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return self.identifiers.count
    }

    func presentationIndexForPageViewController(pageViewController: UIPageViewController!) -> Int {
        return 0
    }

}

这篇帖子对我很有帮助


为什么我的代码不起作用?https://dev59.com/5Ijca4cB1Zd3GeqPtjp0 - Nurdin

1
请注意,此代码仅适用于两个ViewController。如果您计划使用更多,请更改以下行:
self.index = self.index + 1

在调用前后找到,用于:
self.index = index + 1

调用当前的ViewController索引。

1

当然,FirstViewController是你的故事板中的初始视图控制器。

在你的故事板中添加一个自定义的UIPageViewController子类,将其标记为initial,并在其中完成所有工作,在你的UIPageViewController子类中通过storyboardIDs实例化页面控制器成员,在另一个类中也可以执行相同的操作。


@StonePreston 是的,一切都应该没问题。 - iiFreeman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接