我如何创建一个 UIPageViewController,其中所有屏幕都不同并且有自己的 ViewControllers?

How I can create an UIPageViewController where are all screens different and has own ViewControllers?

我想在屏幕之间使用很酷的滑动动画 - UIPageViewController(是的,你知道介绍屏幕的样式),但是我在 Internet 上找到的所有代码和 Github对我没用。

我在 Storyboard 界面中发现只有一个 UIViewController 的演示,几乎所有应用程序都展示了如何从数组更改图像源。看了苹果的参考资料,没看懂

我的 Storyboard 需要一些 ViewControllers(我想将 UIPageViewController 中的所有屏幕设计成不同的,它们将连接到自己的 ViewControllers 类) 谁将出现在 UIPageViewController.

当然,如果您知道更好的方法,请说出来!但我需要的是滑动屏幕随你移动的功能。

有人知道怎么做吗?

我认为您可以利用 View Controller Containment。 我们在这里处理 4 个元素。

  • 主视图控制器
  • 滚动视图
  • UIPage 控件
  • 详细视图控制器

您可以添加滚动视图和页面控件作为主视图控制器的属性。主控制器将处理滚动逻辑,基本上同步滚动视图和页面控件之间的水平滚动。 滚动视图的内容将由所有详细视图控制器的根视图构成。

UIPageViewController 中没有任何内容要求各种视图控制器相同 class。因此,只需实现 viewControllerBeforeViewControllerviewControllerAfterViewController 以及 return 不同类型的视图控制器。如果你想从故事板中引用子视图控制器,只需给那些场景唯一的故事板 ID,然后你就可以使用 instantiateViewControllerWithIdentifier。例如,您可能有一个故事板标识符数组,并使用它来确定哪种场景是 "before" 和 "after" 当前场景。

有很多方法可以实现这一点,但您可以这样做:

class ViewController: UIPageViewController, UIPageViewControllerDataSource {

    let identifiers = ["A", "B", "C", "D"]  // the storyboard ids for the four child view controllers

    override func viewDidLoad() {
        super.viewDidLoad()

        self.dataSource = self

        setViewControllers([viewControllerForPage(0)!], direction: .Forward, animated: false, completion: nil)
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
        var page = (viewController as PageDelegate).pageNumber + 1

        return viewControllerForPage(page)
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        var page = (viewController as PageDelegate).pageNumber - 1

        return viewControllerForPage(page)
    }

    func viewControllerForPage(page: Int) -> UIViewController? {
        if page >= 0 && page < identifiers.count {
            let controller = storyboard?.instantiateViewControllerWithIdentifier(identifiers[page]) as? UIViewController
            (controller as PageDelegate).pageNumber = page
            return controller
        }

        return nil
    }
}

显然,如果你想在这里更优雅,你可以维护一个以前实例化的视图控制器的缓存,但确保你响应内存压力并在必要时清除该缓存。但希望这能说明这样一个事实,即页面视图控制器没有任何内容表明子级是控制器的特定 class。

顺便说一句,上面假设每个子视图控制器都符合一个协议来跟踪页码。

/// Page delegate protocol
///
/// This is a protocol implemented by all of the child view controllers. I'm using it
/// just to keep track of the page number. In practical usage, you might also pass a
/// reference to a model object, too.

@objc protocol PageDelegate {
    var pageNumber: Int { get set }
}

如果你想走完全不同的方向,另一种方法是使用标准故事板,你有一个接一个呈现视图控制器的 segues,然后为每个视图控制器实现滑动手势识别器,从右边滑动执行 segue 以过渡到下一个场景(例如 IBAction 执行 performSegueWithIdentifier),另一个滑动手势识别器(从左到右)将关闭视图控制器。

最后,如果您希望这些手势识别器具有交互性(例如跟随用户的手指),您可以使用自定义转换,并结合交互式转换。有关详细信息,请参阅 WWDC 2013 视频 Custom Transitions Using View Controllers or WWDC 2014 videos View Controller Advancements in iOS 8 (which, about 20 minutes into the video, describes how custom transitions have been enhanced in iOS 8 with presentation controllers) and A Look Inside Presentation Controllers