簡體   English   中英

將數據傳遞給 TabBar 控制器

[英]Pass data to TabBar Controller

我想在兩個 ViewControllers 之間傳遞數據拋出 TabBarController。 在第一個 ViewController 中,我找到了 textField 和按鈕。 在第二個里面我找到了標簽。 當我在 textField 和按鈕中寫入一些文本時,我希望該文本出現在第二個 ViewController 的 Label 中。 但什么也沒有發生。

還有我的代碼:

第一個視圖控制器:

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.
    }


}

第二個視圖控制器:

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.
    }


}

在此處輸入圖片說明

我認為問題出在

tabBarController.viewControllers?.first as? SecondViewController

你可能想這樣做:

tabBarController.viewControllers?[1] as? SecondViewController

不要忘記數組從 0 開始索引,所以viewControllers?[1]實際上返回數組中的第二個元素。

首先,我認為表示選項卡的視圖控制器應該嵌入到導航控制器中,然后將其鏈接到 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 變量中,它會起作用(不確定)。

然而,這是使用協議(委托)的解決方案,這是在控制器之間發送數據的正確方法。 提出您可能有的任何問題。 這應該有效:

第一個視圖控制器:

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.
    }


}

第二視圖控制器:

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
    }

}

我不建議你這樣做。 這是理解的解釋。

  1. 在tabBarController的viewControllers知道他們tabBarController 您可以使用self.tabBarController訪問它。
  2. secondViewControllerviewControllers列表中的第二個,所以let second = tabBarController.viewControllers?[1] as? SecondViewController viewControllers let second = tabBarController.viewControllers?[1] as? SecondViewController let second = tabBarController.viewControllers?[1] as? SecondViewController
  3. 如果你還沒有訪問secondViewController ,它的視圖不會加載,所以出口仍然是nil 您可以使用_ = second.view強制加載視圖。
  4. 如果要切換到第二個選項卡,則需要使用tabBarController.selectedIndex = 1

@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 ?? ""

然后將該字符串分配給viewWillAppear覆蓋中的label

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

viewWillAppear設置它的原因是viewWillAppear將在每次顯示視圖之前運行。 viewDidLoad只會在第一次加載視圖時運行一次。 由於您希望該功能多次工作,因此viewWillAppear是正確的覆蓋。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM