将数据传递给TabBar控制器

时间:2017-11-17 20:51:37

标签: ios iphone swift tabbar

我想在两个ViewControllers之间传递数据抛出TabBarController。 在第一个ViewController里面我找到了textField和button。 在第二个我找到标签。 当我在textField和push按钮中写一些文本时,我希望这个文本出现在第二个ViewController的Label中。但没有任何反应。

我的代码:

First ViewController:

import UIKit

class FirstViewController: UIViewController {
    @IBOutlet weak var textField: UITextField!

    @IBAction func enter(_ sender: Any) {
        if textField.text != "" {
            if let window = UIApplication.shared.delegate?.window, let tabBarController = window?.rootViewController as? UITabBarController, let second = tabBarController.viewControllers?.first as? SecondViewController {
                second.label.text = textField.text
                tabBarController.selectedIndex = 0
            }
        }
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

第二个ViewController:

import UIKit

class SecondViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    var myString = String()

    override func viewDidLoad() {
        super.viewDidLoad()

        label.text = myString
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

enter image description here

3 个答案:

答案 0 :(得分:0)

我认为问题在于

tabBarController.viewControllers?.first as? SecondViewController

你可能想要这样做:

tabBarController.viewControllers?[1] as? SecondViewController

不要忘记数组从0开始索引,因此viewControllers?[1]实际上返回数组中的第二个元素。

答案 1 :(得分:0)

首先,我认为代表制表符的视图控制器应嵌入到导航控制器中,然后导航控制器将链接到TabBarController。

其次,在控制器之间发送数据的优先和推荐方法是通过协议(委托)。这是一个很好的例子,您可以一步一步地查看:https://medium.com/@jamesrochabrun/implementing-delegates-in-swift-step-by-step-d3211cbac3ef

但是,如果您正在寻找解决方案的快速解决方案,我认为Bruno Phillipe的答案在某种程度上得到了它,但并不完全。我们无法确定控制器在视图控制器列表中的哪个索引处。我认为这应该有效:

@IBAction func enter(_ sender: Any) {
    if textField.text != "" {
        if let window = UIApplication.shared.delegate?.window, let tabBarController = window?.rootViewController as? UITabBarController {

            //check if there are view controllers in the tabBarController
            guard let vcList = tabBarController.viewControllers else {

                return
            }

            for controller in vcList {

                if let second = controller as? SecondViewController {
                    //this will be executed only when a controller is SeconfViewController
                    second.label.text = textField.text
                    tabBarController.selectedIndex = 0
                }
            }

        }
    }
}

编辑:

我自己尝试了,问题是你试图设置label.text,实际上标签组件从未初始化。我想如果你只是将textField值存储到SecondViewController中的myString变量中,它就可以工作(不确定)。

然而,这是使用协议(委托)的解决方案,这是在控制器之间发送数据的正确方法。问你可能有任何问题。这应该有效:

FirstViewController:

import Foundation
import UIKit

protocol LabelChangeDelegate: class {

    func changeLabelWithText(_ text: String?)
}

class FirstViewController: UIViewController {

    weak var delegate: LabelChangeDelegate?

    @IBOutlet weak var textField: UITextField!

    @IBAction func enter(_ sender: UIButton) {

        if textField.text != "" {
            if let window = UIApplication.shared.delegate?.window, let tabBarController = window?.rootViewController as? UITabBarController {

                //check if there are view controllers in the tabBarController
                guard let vcList = tabBarController.viewControllers else {

                    return
                }

                for controller in vcList {

                    if let second = controller as? SecondViewController {
                        //this will be executed only when a controller is SeconfViewController

                        //set the delegate - who needs the data
                        delegate = second
                        //call the delegate function which will commmunicate with the delegate
                        delegate?.changeLabelWithText(textField.text!)
                        //don't know why you need this
                        tabBarController.selectedIndex = 0
                    }
                }

            }
        }
    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    }

    override func viewDidLoad() {
         super.viewDidLoad()
         // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
         super.didReceiveMemoryWarning()
         // Dispose of any resources that can be recreated.
    }


}

SecondViewController:

import Foundation
import UIKit

class SecondViewController: UIViewController, LabelChangeDelegate {

    @IBOutlet weak var label: UILabel!

    //lazy init
    lazy var myString = String()

    override func viewDidLoad() {
        super.viewDidLoad()

        //set label when the view loads, not in the first controller
        label.text = myString

        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
         super.didReceiveMemoryWarning()
         // Dispose of any resources that can be recreated.
    }

    //delegate function
    func changeLabelWithText(_ text: String?) {
        guard let sentText = text else {

            //no text sent
            return
        }

        myString = sentText
    }

}

答案 2 :(得分:0)

我不建议你这样做。这是对理解的解释。

  1. tabBarController中的viewControllers知道他们的tabBarController。您可以使用self.tabBarController
  2. 访问它
  3. secondViewControllerviewControllers列表中的第二个let second = tabBarController.viewControllers?[1] as? SecondViewController
  4. 如果您尚未访问secondViewController,则其视图将无法加载,因此网点仍为nil。您可以使用_ = second.view
  5. 强制加载视图
  6. 如果您想切换到第二个标签,则需要使用tabBarController.selectedIndex = 1
  7. @IBAction func enter(_ sender: Any) {
        if textField.text != "" {
            if let tabBarController = self.tabBarController as? UITabBarController, let second = tabBarController.viewControllers?[1] as? SecondViewController {
                // make sure view has loaded
                _ = second.view
    
                second.label.text = textField.text
    
                // change to second tab
                tabBarController.selectedIndex = 1
            }
        }
    }
    

    更好的方法......

    您应该将字符串传递给SecondViewController的属性,而不是直接设置插座:

    second.myString = textField.text ?? ""
    

    然后在label的覆盖中将该字符串分配给viewWillAppear

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        label.text = myString
    }
    

    viewWillAppear中设置它的原因是viewWillAppear每次都会在显示视图之前运行。 viewDidLoad只会在首次加载视图时运行一次。由于您希望功能多次工作,viewWillAppear是正确的覆盖。