![](/img/trans.png)
[英]pass data from tabbar controller to view controller in swift and xcode
[英]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
}
}
我不建議你這樣做。 這是理解的解釋。
tabBarController
。 您可以使用self.tabBarController
訪問它。secondViewController
是viewControllers
列表中的第二個,所以let second = tabBarController.viewControllers?[1] as? SecondViewController
viewControllers
let second = tabBarController.viewControllers?[1] as? SecondViewController
let second = tabBarController.viewControllers?[1] as? SecondViewController
。secondViewController
,它的視圖不會加載,所以出口仍然是nil
。 您可以使用_ = second.view
強制加載視圖。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.