在 UIPageViewController 中以编程方式转到下一页

Posted

技术标签:

【中文标题】在 UIPageViewController 中以编程方式转到下一页【英文标题】:Go to the next Page programmatically within a UIPageViewController 【发布时间】:2016-07-12 13:37:02 【问题描述】:

我有一个 rootViewController,它基本上是我的 pageViewController,它实现了所有的页面控制器协议功能。我已经成功地实现了整个 pageViewController,其 pageControl 可以正确显示当前页码。

在包含在 rootViewController 中的第一页上,我有一个 viewController,其中有多个 textFields 必须用 pickerView 填充。我还创建了一个伴随选择器的 inputAccessory 工具栏。一旦所有字段都填充了文本,工具栏上的 barButton 就会切换到完成。在这个 viewController 中点击这个“完成”按钮,我希望 rootViewController 转到下一页。

我首先尝试直接呈现我想转向的 viewController,但注意到该页面并未作为 pageViewController 的一部分呈现(看起来很明显为什么它现在不起作用!)。所以我然后尝试实现一个协议,该协议将触发 rootViewController 转到下一页。我已经完美地实现了一切,但没有设置委托。我似乎无法理解为什么它没有被设置。这可能是因为我在 UIPageViewController 框架流程中遗漏了一些东西吗?我难住了。

最终在协议中我试图在包含的 ViewController 和 rootViewController 之间进行通信。

这是我的源代码:

在根控制器中:

    import UIKit

    class rootPageViewController: UIViewController, UIPageViewControllerDataSource,
    UIPageViewControllerDelegate, tutorialPageTurnerDelegate 

        var tutorialOne = userInputViewController()

        @IBOutlet var pageLight: UIPageControl!

        var turn: UIPageViewController!
        let pages = ["userInput","tutorialOne","tutorialTwo","connectScreen"]
        var i: Int!

        override func viewDidLoad() 
            super.viewDidLoad()

            if let take = storyboard?.instantiateViewControllerWithIdentifier("pageView") 

                self.addChildViewController(take)
                self.view.addSubview(take.view)
                take.view.addSubview(pageLight)
                take.view.bringSubviewToFront(pageLight)

                turn = take as! UIPageViewController
                turn.dataSource = self
                turn.delegate = self

                // the delegate for the protocol I've implemented 
                tutorialOne.delegate = self

                turn.setViewControllers([viewControllerAtIndex(0)!], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
                turn.didMoveToParentViewController(self)

            

        

       .
       .
       ... pageviewcontroller protocol functions and misc code ...
       .
       .

 // Helper Function to return Index
    func viewControllerAtIndex(index: Int) -> UIViewController? 

        let vc = storyboard?.instantiateViewControllerWithIdentifier(pages[index])

// _________EDIT_________
    if index == 0 
                var tutorialOne: userInputViewController = userInputViewController()
                tutorialOne.delegate = self
            
        return vc

    


// function required by the protocol
func saveActionCompleted() 

        print("Yes it does come here")
        turn.setViewControllers([viewControllerAtIndex(1)!], direction: UIPageViewControllerNavigationDirection.Forward, animated: true, completion: nil)
        turn.didMoveToParentViewController(self)

    
...

现在这里是我创建协议的视图控制器:

import UIKit
import CoreData

protocol tutorialPageTurnerDelegate 
    func saveActionCompleted()


class userInputViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate,
UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate 


    var delegate: tutorialPageTurnerDelegate?

override func viewDidLoad() 
        super.viewDidLoad()

 //Create toolbar
                let toolBar = UIToolbar()
                toolBar.barStyle = UIBarStyle.Default
                toolBar.translucent = true
                toolBar.tintColor = UIColor(red: 81/255, green: 45/255, blue: 168/255, alpha: 1)
                toolBar.sizeToFit()

let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Plain, target: self, action: "donePicker")
                let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
                toolBar.setItems([spaceButton, nextButton], animated: false)
                toolBar.userInteractionEnabled = true

....... more misc code ...



// The selector function for the toolbar from where I want to notify the root controller
 func donePicker()

        self.view.endEditing(true)
        saveDataAction(self)

        if delegate != nil 
            delegate!.saveActionCompleted()
         else 
            print("PageTurnerDelegate is nil")
        
     
...
 //End

我得到 PageTurnerDelegate 为零。我尝试了很多解决方法,但都徒劳无功。我确实觉得可能有更好的方法来做到这一点。欢迎任何建议或见解!

【问题讨论】:

我看不到您将 tutorialOne 变量设置为第一个视图控制器的位置。可以显示viewControllerAtIndex 吗? 我已经进行了编辑。你可以在rootViewController代码sn-p中看到viewControllerAtIndex 因此,在该方法中,您正在实例化一个新的视图控制器,但您从未设置委托。因此,您有一个视图控制器实例tutorialOne,您在其中设置了委托,但您从不显示此实例,那么您将拥有viewControllerAtIndex 返回的其他视图控制器实例,您从未设置过委托 好的,所以我进入viewControllerAtIndex 函数并尝试在其中设置tutorialOne 的委托,但仍未设置。您能否详细说明“您从不显示此实例”是什么意思? 我的意思是你分配了一个userInputViewController 的实例并将它放在tutorialOne 中,但你实际上从未显示tutorialOne。在viewControllerAtIndex 中设置委托应该可以工作 【参考方案1】:

您需要设置将要显示的视图控制器实例的delegate 属性:

func viewControllerAtIndex(index: Int) -> UIViewController? 

    let vc = storyboard?.instantiateViewControllerWithIdentifier(pages[index])
    if index == 0 
            let userInputViewController =vc as! userInputViewController
            userInputViewController.delegate = self
    
    return vc

另外,按照惯例,类以大写字母开头,所以应该是UserInputViewController

【讨论】:

当然我会记住这一点。非常感谢您的建议。该协议现在正在运行。

以上是关于在 UIPageViewController 中以编程方式转到下一页的主要内容,如果未能解决你的问题,请参考以下文章

屏幕关闭时如何在 UIPageViewController 中以编程方式翻页?

在 UIPageViewController 中以编程方式转到下一页

UIPageControl(页面控件)不显示在 UIPageViewController

ViewDidLoad 不断在 UIPageViewController 上被调用

UIPageViewController 背景在 Objective C iOS 中从不透明

获取 UIPageViewController 的滚动位置