如何从属于 UIPageViewController 的 UIViewController 之一更改 UIPageViewController?

Posted

技术标签:

【中文标题】如何从属于 UIPageViewController 的 UIViewController 之一更改 UIPageViewController?【英文标题】:How do I change the UIPageViewController from WITHIN one of the UIViewControllers that is part of the UIPageViewController? 【发布时间】:2016-11-04 16:17:07 【问题描述】:

我已经尝试解决这个问题好几个小时了,我一定是误解了 UIPageViewController 的工作原理。

我有 5 个设置屏幕(加载到 UIPageViewController 的单独视图控制器),我可以向右 + 向左滑动来查看。

但是!我希望能够在他们关闭其中一个视图控制器上的警报后以编程方式显示下一个视图控制器。

到目前为止,我发现唯一接近的解决方案是这里的解决方案 (https://github.com/jeffaburt/UIPageViewController-Post),它允许“下一步”按钮,但该按钮不在视图控制器上显示,它位于拥有UIPageViewController 的根视图控制器上。

我已将UIPageViewController 设置为显示 5 个不同的视图控制器,并使用此代码。

private(set) lazy var orderedViewControllers: [UIViewController] = 
    return [self.newColoredViewController("setup1"),
            self.newColoredViewController("setup2"),
            self.newColoredViewController("setup3"),
            self.newColoredViewController("setup4"),
            self.newColoredViewController("setup5")]
()

然后newColoredViewController 函数会这样做:

private func newColoredViewController(color: String) -> UIViewController 
    return UIStoryboard(name: "Main", bundle: nil) .
        instantiateViewControllerWithIdentifier("\(color)")

这是我的viewDidLoad

 override func viewDidLoad() 
    super.viewDidLoad()

    dataSource = self



    if let SetupViewController = orderedViewControllers.first 
        setViewControllers([SetupViewController],
                           direction: .Forward,
                           animated: true,
                           completion: nil)
    



我一定缺少一些基本的理解,因为我尝试了很多不同的方法来以编程方式更改页面,但没有任何反应。

我试过这样做,但什么也没做:

setViewControllers([orderedViewControllers[3]],
                           direction: .Forward,
                           animated: true,
                           completion: nil)

我试过这样做,但什么也没做:

func scrollToNextViewController() 
    if let visibleViewController = viewControllers?.first,
        let nextViewController = pageViewController(self,
                                                    viewControllerAfterViewController: visibleViewController) 
        scrollToViewController(nextViewController)
    

请指点我正确的方向!!我可以研究一整天,并且通常可以通过之前已经回答的 *** 问题弄清楚,但在这里我很难过。

提前致谢!!

【问题讨论】:

【参考方案1】:

我想出了一个更简单的方法来在我已经建立的结构内完成它。在 UIPageViewController 中,添加了这个函数:

func nextPageWithIndex(index: Int)

   // let nextWalkthroughVC = newColoredViewController("setup4")
    let nextWalkthroughVC = orderedViewControllers[index]
        setViewControllers([nextWalkthroughVC], direction: .Forward, animated: true, completion: nil)


然后在其中一个设置视图控制器中,我创建了一个运行此代码的按钮操作:

@IBAction func yeaaa(sender: AnyObject) 
              let parent = self.parentViewController as! SetupViewController

    parent.nextPageWithIndex(3)

(其中“SetupViewController”是 UIPageViewController)

YEEHAWWWW 把我逼疯了。

这是让我想到“self.parentViewController as!SetupViewController”和“nextPageWithIndex”代码的视频:https://www.youtube.com/watch?v=K3CSBxX5VXA

【讨论】:

【参考方案2】:

我猜你在newColoredViewController 中创建了将由pageViewController 显示的视图控制器的实例。

您应该在此处传递对显示视图控制器的引用。就像是 newSetupViewConroller.setNextDelegate(self)

定义一个协议NextDelegate,它有一个方法performNext

那应该是setNextDelegate 的参数类型(以及相关的实例变量)。 (当然也可以使用 setter 方法声明NextDelegate 类型的一些属性)

您的呈现视图控制器应符合此协议并实现performNext 方法。

当你这样做时,你就可以访问呈现视图控制器(作为一个符合协议的对象),你可以调用它的方法performNext

performNext 方法中,您在呈现视图控制器中并可以访问pageViewController 并从那里开始。

(有更简单的方法可以做到这一点,但我认为这是一个合适的方法。这就是协议的目的。)

【讨论】:

确认!我几乎不明白如何实现你刚才解释的内容。那么,我应该更改函数private func newColoredViewController(color: String) -> UIViewController return UIStoryboard(name: "Main", bundle: nil) . instantiateViewControllerWithIdentifier("\(color)") 并尝试传入一个变量吗?当您说“传入对显示视图控制器的引用时,我该怎么做? 你说有更简单的方法可以做到这一点——你能解释一下吗?我完全赞成正确的做事方式,但老实说,我认为我无法实现你解释的内容,因为我还不是那个级别的编码员! 是的,不要直接返回实例,而是将它保存在一些局部变量中,然后传入呈现的视图控制器。但我的建议是不要将参数声明为呈现视图控制器的类的对象,而是在两者之间使用协议。两种方式的类耦合效果很好,但不是很好的风格。 你可以省略协议。然后你有一个A类“知道”B类。到目前为止还可以。但是你也必须让 B 类“知道”A 类。这是应该避免的循环依赖。更好的是声明协议 C 并使 A 实现/符合协议。这样做,B 只需要“知道”协议 C。这可以达到目的,但避免了循环依赖。 (这是 ios 中常用的委托模式的一个示例。) 有经验的程序员可能会发现 lamda 表达式更方便。它们当然是更少的编码工作,并且具有将两个类解耦的相同目的,但是正如您所说的那样,您不是编码员,委托模式就可以了。【参考方案3】:

首先,我们需要访问父类为 PageViewController

斯威夫特 5:

   if let controller = self.parent as? yourPageViewController             
          controller.goToNextPage()
   

PageViewController Extension可以这样使用

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)
    

【讨论】:

以上是关于如何从属于 UIPageViewController 的 UIViewController 之一更改 UIPageViewController?的主要内容,如果未能解决你的问题,请参考以下文章

如何从属于 UIPageViewController 的 UIViewController 之一更改 UIPageViewController?

如何从sequelize中的实例中排除关联属于多?

MongoDb复杂查询:如何从属于“用户”的“书”中查询一些“页面”

如何从 YouTube Analytics API 获取属于当前用户的每个视频的指标?

如何从属于 UITableView 中的模型数组对象的数组中向 tableView 显示数据?

Laravel“属于”功能。不完全确定这是如何工作的。帮助从 Blade 模板访问相关模型信息