PageViewController-将变量传递给子视图 [英] PageViewController - Pass variables to child views

查看:76
本文介绍了PageViewController-将变量传递给子视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆