你如何将数据从 ViewController 传递到包含单独 ViewController 的 PageViewController,然后这些 ViewController 将使用这些数据?
Posted
技术标签:
【中文标题】你如何将数据从 ViewController 传递到包含单独 ViewController 的 PageViewController,然后这些 ViewController 将使用这些数据?【英文标题】:How do you pass data from a ViewController to a PageViewController containing separate ViewControllers which will then use this data? 【发布时间】:2015-06-15 17:14:19 【问题描述】:我基本上有一个根 ViewController,我想将它传递到通过 PageViewController 连接的 ViewControllers 集合(所有不同的类本身)。
目前,我在根 ViewController 中设置了一个 prepareforsegue 来传递数据。然后我在 PageViewController 中声明了变量,并试图弄清楚如何将数据传递到 ViewControllers。
我目前只是在做一个简单的 Hello World 测试,所以我的代码有点简单。这是我的 RootViewController,我已将其传递到 PageViewController(并因此传递到连接到 PageViewController 的后续 VC):
class RootViewController: UIViewController
override func viewDidLoad()
super.viewDidLoad()
var hello: String! = "Hello World!"
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
if (segue.identifier == "testSegue")
var svc = segue.destinationViewController as! PageViewController;
svc.datapassed = self.hello
我的 PageView 控制器有点复杂。我正在使用情节提要 ID 方法,因为我希望 pageviewcontroller 显示不同类的视图控制器,而不是显示一个视图控制器模板和不同图像内容的大量教程......
class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate
var datapassed: String!
var index = 0
var identifiers: NSArray = ["FirstNavigationController", "SecondNavigationController"]
override func viewDidLoad()
super.viewDidLoad()
setupPageControl()
self.dataSource = self
self.delegate = self
let startingViewController = self.viewControllerAtIndex(self.index)
let viewControllers: NSArray = [startingViewController]
self.setViewControllers(viewControllers as [AnyObject], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
// Do any additional setup after loading the view.
func viewControllerAtIndex(index: Int) -> UIViewController!
if index == 0
return self.storyboard!.instantiateViewControllerWithIdentifier("FirstNavigationController") as! UIViewController
if index == 1
return self.storyboard!.instantiateViewControllerWithIdentifier("SecondNavigationController") as! UIViewController
return nil
func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController!
let identifier = viewController.restorationIdentifier
let index = self.identifiers.indexOfObject(identifier!)
if index == identifiers.count - 1
return nil
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 index == 0
return nil
self.index = self.index - 1
return self.viewControllerAtIndex(self.index)
private func setupPageControl()
let appearance = UIPageControl.appearance()
appearance.pageIndicatorTintColor = UIColor.grayColor()
appearance.currentPageIndicatorTintColor = UIColor.whiteColor()
func presentationCountForPageViewController(pageViewController: UIPageViewController!) -> Int
return self.identifiers.count
func presentationIndexForPageViewController(pageViewController: UIPageViewController!) -> Int
return 0
最后,我只是想让第一个 ViewController 连接到 pageviewcontroller 以显示来自传递的变量 datapassed 的文本。
class FirstViewController: UIViewController
@IBOutlet weak var helloLabel: UILabel!
override func viewDidLoad()
super.viewDidLoad()
helloLabel.text = datapassed
// Do any additional setup after loading the view.
编辑: 可能的解决方案和最终代码:
class RootViewController: UIViewController
override func viewDidLoad()
super.viewDidLoad()
var carinfos: String! = "Hello World"
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
if let svc = segue.destinationViewController as? PageViewController
where segue.identifier == "testSegue"
svc.dataPassed = self.carinfos
class PageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate
var dataPassed: String?
didSet
self.updateCurrentViewController()
var index = 0
var identifiers: NSArray = ["FirstNavigationController", "SecondNavigationController"]
override func viewDidLoad()
super.viewDidLoad()
self.dataSource = self
self.delegate = self
let startingViewController = self.viewControllerAtIndex(self.index)
let viewControllers: NSArray = [startingViewController]
self.setViewControllers(viewControllers as [AnyObject], direction: UIPageViewControllerNavigationDirection.Forward, animated: false, completion: nil)
func updateCurrentViewController()
if let firstViewController = self.viewControllerAtIndex(self.index) as? FirstViewController, let data = self.dataPassed
firstViewController.dataPassed = data
func pageViewController(pageViewController: UIPageViewController!, viewControllerAfterViewController viewController: UIViewController!) -> UIViewController!
let identifier = viewController.restorationIdentifier
let index = self.identifiers.indexOfObject(identifier!)
if index == identifiers.count - 1
return nil
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 index == 0
return nil
self.index = self.index - 1
let viewController = self.viewControllerAtIndex(self.index)
self.updateCurrentViewController()
return viewController
func viewControllerAtIndex(index: Int) -> UIViewController!
if index == 0
return self.storyboard!.instantiateViewControllerWithIdentifier("FirstNavigationController") as! UIViewController
if index == 1
return self.storyboard!.instantiateViewControllerWithIdentifier("SecondNavigationController") as! UIViewController
return nil
func presentationCountForPageViewController(pageViewController: UIPageViewController!) -> Int
return self.identifiers.count
func presentationIndexForPageViewController(pageViewController: UIPageViewController!) -> Int
return 0
class FirstViewController: UIViewController
var dataPassed: String?
@IBOutlet weak var firstLabelTest: UILabel!
@IBOutlet weak var firstLabel: UILabel!
override func viewDidLoad()
super.viewDidLoad()
println(dataPassed)
firstLabel.text = "Hello, this is First"
self.populateData()
func populateData()
if let data = self.dataPassed
self.firstLabelTest.text = self.dataPassed
【问题讨论】:
【参考方案1】:您可以简单地将其传递给视图控制器结构以使其正常工作,尽管这并不是一个深思熟虑的设计。为此,首先,确保您使用if let
绑定和有条件的向下转换 (as?
) 正确地转换了 destinationViewController
。您还可以使用where
子句将比较与segue 的identifier
结合起来。然后,您将拥有设置数据的对象。
在FirstViewController
中,使用属性观察器在设置dataPassed
变量时更新标签,并在viewDidLoad
上更新它。
此外,您的 hello
属性不应是隐式展开的类型,因此您可以从声明中删除 !
。
class FirstViewController : UIViewController
@IBOutlet weak var helloLabel: UILabel!
var dataPassed: String?
override func viewDidLoad()
super.viewDidLoad()
self.populateData()
func populateData()
if let data = self.dataPassed
self.helloLabel.text = self.dataPassed
class PageViewController : UIPageViewController
var index = 0
var identifiers: NSArray = ["FirstNavigationController", "SecondNavigationController"]
var dataPassed: String?
didSet
self.updateCurrentViewController()
func pageViewController(pageViewController: UIPageViewController!, viewControllerBeforeViewController viewController: UIViewController!) -> UIViewController!
let identifier = viewController.restorationIdentifier
let index = self.identifiers.indexOfObject(identifier!)
if index == 0
return nil
self.index = self.index - 1
let viewController = self.viewControllerAtIndex(self.index)
self.updateCurrentViewController()
return viewController
func updateCurrentViewController()
if let firstViewController = self.viewControllerAtIndex(self.index) as? FirstViewController, let data = self.dataPassed
firstViewController.dataPassed = data
func viewControllerAtIndex(index: Int) -> UIViewController!
// Create your VC as in the project template
return nil
class RootViewController : UIViewController
var hello: String = "Hello World!"
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
super.prepareForSegue( segue, sender: sender )
if let svc = segue.destinationViewController as? PageViewController
where segue.identifier == "testSegue"
svc.dataPassed = self.hello
【讨论】:
感谢您的回复。我想知道当您在 FirstViewController 中声明 dataPassed 时 didset 方法做了什么。此外,该行实际上是如何从 RootViewController 提取数据传递的,因为在情节提要上,segue 实际上是从 RootView 到 PageViewController? 对不起,我误解了你的结构,答案已更新。 啊。我觉得我很接近。我摆弄了几个小时的代码,但我无法让数据通过。该项目构建没有任何错误。但是,只是 dataPassed 在 FirstViewController 中不断返回 nil。我已经从上面更新了我的代码,我很确定我没有犯错,但不太确定。【参考方案2】:根据您的应用程序的需求和其他结构,您还可以使用响应者链向层次结构中的任何视图控制器提供数据。
那么就这么简单:
class FirstViewController : UIViewController
@IBOutlet weak var helloLabel: UILabel!
var dataPassed: String?
didSet
if let data = self.dataPassed
self.helloLabel.text = data
override func viewWillAppear(animated: Bool)
super.viewWillAppear(animated)
if let dataSource = self.nextResponder()?.targetForAction( "hello", withSender: self ) as? RootViewController
self.dataPassed = dataSource.hello
class RootViewController : UIViewController
var hello: String = "Hello World!"
【讨论】:
【参考方案3】:在swift3
你可以这样做
在您嵌入 pageviewcontroller 的主视图中,您可以使用带有标识符的 segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if segue.identifier=="challengepostssegue"
let destination=segue.destination as! PageMainController
destination.challengeId=challengId
在PageMainController中声明一个变量可选类型
var challengeId:String?
【讨论】:
以上是关于你如何将数据从 ViewController 传递到包含单独 ViewController 的 PageViewController,然后这些 ViewController 将使用这些数据?的主要内容,如果未能解决你的问题,请参考以下文章
如何将数据从 AppDelegate 传递到 ViewController?
教程/示例:如何将数据从 ViewController 传递到另一个 XCODE [关闭]
如何将数据库从 AppDelegate 传递到 ViewController
如何将数据从可解码模型传递或实现到 ViewController?