PageViewController-将变量传递给子视图 [英] PageViewController - Pass variables to child views
问题描述
我有一个ViewController(TutorialViewController)和一个UIPageViewController(TutorialPageViewController).带有StoryBoard ID的情节提要中还有3个额外的视图:
I have a ViewController (TutorialViewController) and a UIPageViewController (TutorialPageViewController). There are also 3 extra views on the storyboard with StoryBoard ID's:
- GreenViewController
- BlueViewController
- RedViewController
我一直在关注教程(作者,写得很好).
I have been following this tutorial (Kudos to the author, very well written).
在Green View Controller上,我定义了一个变量:
On the Green View Controller I have defined a variable:
var passedVariable = ""
然后在ViewDidLoad中将其打印出来.
And in the ViewDidLoad I print it out.
以下是两个具有代码的控制器:
Here are the two controllers that have the code:
class TutorialViewController: UIViewController {
@IBOutlet weak var pageControl: UIPageControl!
@IBOutlet weak var containerView: UIView!
var tutorialPageViewController: TutorialPageViewController? {
didSet {
tutorialPageViewController?.tutorialDelegate = self
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let tutorialPageViewController = segue.destinationViewController as? TutorialPageViewController {
self.tutorialPageViewController = tutorialPageViewController
}
}
@IBAction func didTapNextButton(sender: UIButton) {
tutorialPageViewController?.scrollToNextViewController()
}
}
extension TutorialViewController: TutorialPageViewControllerDelegate {
func tutorialPageViewController(tutorialPageViewController: TutorialPageViewController,
didUpdatePageCount count: Int) {
pageControl.numberOfPages = count
}
func tutorialPageViewController(tutorialPageViewController: TutorialPageViewController,
didUpdatePageIndex index: Int) {
pageControl.currentPage = index
}
}
UIPageViewController
class TutorialPageViewController: UIPageViewController {
weak var tutorialDelegate: TutorialPageViewControllerDelegate?
//let vc0 = GreenViewController(nibName: "GreenViewController", bundle: nil)
private(set) lazy var orderedViewControllers: [UIViewController] = {
// The view controllers will be shown in this order
return [self.newColoredViewController("Green"),
self.newColoredViewController("Red"),
self.newColoredViewController("Blue"), self.newColoredViewController("Pink")]
}()
override func viewDidLoad() {
super.viewDidLoad()
//self.vc0.passedVariable = "Passed Data"
dataSource = self
delegate = self
if let initialViewController = orderedViewControllers.first {
scrollToViewController(initialViewController)
}
tutorialDelegate?.tutorialPageViewController(self,
didUpdatePageCount: orderedViewControllers.count)
}
/**
Scrolls to the next view controller.
*/
func scrollToNextViewController() {
if let visibleViewController = viewControllers?.first,
let nextViewController = pageViewController(self,
viewControllerAfterViewController: visibleViewController) {
scrollToViewController(nextViewController)
}
}
private func newColoredViewController(color: String) -> UIViewController {
return UIStoryboard(name: "Main", bundle: nil) .
instantiateViewControllerWithIdentifier("\(color)ViewController")
}
/**
Scrolls to the given 'viewController' page.
- parameter viewController: the view controller to show.
*/
private func scrollToViewController(viewController: UIViewController) {
setViewControllers([viewController],
direction: .Forward,
animated: true,
completion: { (finished) -> Void in
// Setting the view controller programmatically does not fire
// any delegate methods, so we have to manually notify the
// 'tutorialDelegate' of the new index.
self.notifyTutorialDelegateOfNewIndex()
})
}
/**
Notifies '_tutorialDelegate' that the current page index was updated.
*/
private func notifyTutorialDelegateOfNewIndex() {
if let firstViewController = viewControllers?.first,
let index = orderedViewControllers.indexOf(firstViewController) {
tutorialDelegate?.tutorialPageViewController(self,
didUpdatePageIndex: index)
}
}
}
// MARK: UIPageViewControllerDataSource
extension TutorialPageViewController: UIPageViewControllerDataSource {
func pageViewController(pageViewController: UIPageViewController,
viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.indexOf(viewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
// User is on the first view controller and swiped left to loop to
// the last view controller.
guard previousIndex >= 0 else {
return orderedViewControllers.last
}
guard orderedViewControllers.count > previousIndex else {
return nil
}
return orderedViewControllers[previousIndex]
}
func pageViewController(pageViewController: UIPageViewController,
viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
guard let viewControllerIndex = orderedViewControllers.indexOf(viewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = orderedViewControllers.count
// User is on the last view controller and swiped right to loop to
// the first view controller.
guard orderedViewControllersCount != nextIndex else {
return orderedViewControllers.first
}
guard orderedViewControllersCount > nextIndex else {
return nil
}
return orderedViewControllers[nextIndex]
}
}
extension TutorialPageViewController: UIPageViewControllerDelegate {
func pageViewController(pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool) {
notifyTutorialDelegateOfNewIndex()
}
}
protocol TutorialPageViewControllerDelegate: class {
/**
Called when the number of pages is updated.
- parameter tutorialPageViewController: the TutorialPageViewController instance
- parameter count: the total number of pages.
*/
func tutorialPageViewController(tutorialPageViewController: TutorialPageViewController,
didUpdatePageCount count: Int)
/**
Called when the current index is updated.
- parameter tutorialPageViewController: the TutorialPageViewController instance
- parameter index: the index of the currently visible page.
*/
func tutorialPageViewController(tutorialPageViewController: TutorialPageViewController,
didUpdatePageIndex index: Int)
}
我尝试过的
我尝试像这样首先声明视图控制器:
What I have tried
I have tried declaring the View Controller first like so:
let vc0 = GreenViewController(nibName: "GreenViewController", bundle: nil)
然后像这样传递数据:
override func viewDidLoad() {
vc0.passedVariable = "This was passed, Dance with Joy"
}
控制台中没有任何内容.
Nothing is printing out in the console.
我还尝试将以上捆绑商品更改为:
I also tried changing the bundle above to:
bundle: NSBundle.mainBundle()
还是那达(Nada)
我计划从alamofire请求中将数据加载到TutorialViewController上,我想将该数据传递给ViewController之一(绿色,蓝色,红色)
I plan to load data on the TutorialViewController from an alamofire request, I want to pass that data to one of the ViewControllers (green, blue, red)
如何将已经从TutorialViewController中获取的数据传递给将要加载的子视图之一?
How do I pass data that has been acquired from the TutorialViewController to one of the child views that will load?
推荐答案
首先,我要感谢您检查了我的教程以及您所说的所有美好内容.
First, I want to thank you for checking out my tutorial and all of the nice things you said about it.
第二,我为您提供解决方案!我继续进行操作,并向GitHub存储库提交了解决方案我在教程中链接了 .我还将在此处发布代码.
Second, I have a solution for you! I went ahead and committed the solution to the GitHub repo I linked in the tutorial. I will also post the code here.
(1)创建一个UIViewController
子类以向其中添加自定义属性.在此示例中,我选择添加UILabel
,因为它是运行应用程序时最容易查看的内容.
(1) Create a UIViewController
subclass to add custom properties to. For this example, I chose to add a UILabel
since it's the easiest to view when running the app.
class ColoredViewController: UIViewController {
@IBOutlet weak var label: UILabel!
}
(2)在Main.storyboard
内,在身份检查器中将每个UIViewController
页面"的自定义类更改为ColoredViewController
.
(2) Inside Main.storyboard
, change the custom class for each UIViewController
"page" to ColoredViewController
in the Identity Inspector.
(3)在每个页面"中添加一个UILabel
,并根据需要对其进行约束.我选择将其在容器中垂直和水平居中.不要忘记将UILabel
链接到ColoredViewController
的@IBOutlet weak var label: UILabel!
.
(3) Add a UILabel
to each "page" and constraint it however you'd like. I chose to vertically and horizontally center it in the container. Don't forget to link the UILabel
to ColoredViewController
's @IBOutlet weak var label: UILabel!
.
(4)可选:如果从未在代码中设置标签的文本,则不会删除默认的标签"文本,因此不会向用户显示标签".
(4) Optional: I deleted the default "Label" text in each one that way if we never set the label's text in code, we will not show "Label" to the user.
(5)我们需要对TutorialPageViewController
做一些TLC,因此它知道orderedViewControllers
现在是ColoredViewController
数组.为了简单起见,我将粘贴整个类:
(5) We need to do some TLC to TutorialPageViewController
so it knows that orderedViewControllers
is now a ColoredViewController
array. To make things easy, I'm just going to paste the entire class:
class TutorialPageViewController: UIPageViewController {
weak var tutorialDelegate: TutorialPageViewControllerDelegate?
private(set) lazy var orderedViewControllers: [ColoredViewController] = {
// The view controllers will be shown in this order
return [self.newColoredViewController("Green"),
self.newColoredViewController("Red"),
self.newColoredViewController("Blue")]
}()
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
delegate = self
if let initialViewController = orderedViewControllers.first {
scrollToViewController(initialViewController)
}
tutorialDelegate?.tutorialPageViewController(self,
didUpdatePageCount: orderedViewControllers.count)
}
/**
Scrolls to the next view controller.
*/
func scrollToNextViewController() {
if let visibleViewController = viewControllers?.first,
let nextViewController = pageViewController(self,
viewControllerAfterViewController: visibleViewController) {
scrollToViewController(nextViewController)
}
}
private func newColoredViewController(color: String) -> ColoredViewController {
return UIStoryboard(name: "Main", bundle: nil) .
instantiateViewControllerWithIdentifier("\(color)ViewController") as! ColoredViewController
}
/**
Scrolls to the given 'viewController' page.
- parameter viewController: the view controller to show.
*/
private func scrollToViewController(viewController: UIViewController) {
setViewControllers([viewController],
direction: .Forward,
animated: true,
completion: { (finished) -> Void in
// Setting the view controller programmatically does not fire
// any delegate methods, so we have to manually notify the
// 'tutorialDelegate' of the new index.
self.notifyTutorialDelegateOfNewIndex()
})
}
/**
Notifies '_tutorialDelegate' that the current page index was updated.
*/
private func notifyTutorialDelegateOfNewIndex() {
if let firstViewController = viewControllers?.first as? ColoredViewController,
let index = orderedViewControllers.indexOf(firstViewController) {
tutorialDelegate?.tutorialPageViewController(self,
didUpdatePageIndex: index)
}
}
}
// MARK: UIPageViewControllerDataSource
extension TutorialPageViewController: UIPageViewControllerDataSource {
func pageViewController(pageViewController: UIPageViewController,
viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
guard let coloredViewController = viewController as? ColoredViewController,
let viewControllerIndex = orderedViewControllers.indexOf(coloredViewController) else {
return nil
}
let previousIndex = viewControllerIndex - 1
// User is on the first view controller and swiped left to loop to
// the last view controller.
guard previousIndex >= 0 else {
return orderedViewControllers.last
}
guard orderedViewControllers.count > previousIndex else {
return nil
}
return orderedViewControllers[previousIndex]
}
func pageViewController(pageViewController: UIPageViewController,
viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {
guard let coloredViewController = viewController as? ColoredViewController,
let viewControllerIndex = orderedViewControllers.indexOf(coloredViewController) else {
return nil
}
let nextIndex = viewControllerIndex + 1
let orderedViewControllersCount = orderedViewControllers.count
// User is on the last view controller and swiped right to loop to
// the first view controller.
guard orderedViewControllersCount != nextIndex else {
return orderedViewControllers.first
}
guard orderedViewControllersCount > nextIndex else {
return nil
}
return orderedViewControllers[nextIndex]
}
}
extension TutorialPageViewController: UIPageViewControllerDelegate {
func pageViewController(pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool) {
notifyTutorialDelegateOfNewIndex()
}
}
protocol TutorialPageViewControllerDelegate: class {
/**
Called when the number of pages is updated.
- parameter tutorialPageViewController: the TutorialPageViewController instance
- parameter count: the total number of pages.
*/
func tutorialPageViewController(tutorialPageViewController: TutorialPageViewController,
didUpdatePageCount count: Int)
/**
Called when the current index is updated.
- parameter tutorialPageViewController: the TutorialPageViewController instance
- parameter index: the index of the currently visible page.
*/
func tutorialPageViewController(tutorialPageViewController: TutorialPageViewController,
didUpdatePageIndex index: Int)
}
(6)在TutorialViewController
内部:让我们设置label.text
.我选择使用viewDidLoad
,但可以将此逻辑填充到网络请求完成块中.
(6) Inside TutorialViewController
: let's set the label.text
. I chose to use viewDidLoad
, but feel free to stuff this logic inside a network request completion block.
override func viewDidLoad() {
super.viewDidLoad()
if let greenColoredViewController = tutorialPageViewController?.orderedViewControllers.first {
greenColoredViewController.label.text = "Hello world!"
}
}
希望这会有所帮助!
这篇关于PageViewController-将变量传递给子视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!