how to pass data from UIViewController to TabBrController

here's how it supposed to work

I have a login screen where the user logs in entering their username and password. (the UI is built programmatically)

the login screen inherits from UIViewController after the user clicks the sign-in I make a request to get their information from firebase. and then if the login is successful I create a variable such as
Code Block
let student = Student()


assign the information I grabbed from firebase to the created object student.

and then I do something like

Code Block
let nextController = theTabBarControllerClass()
nextController.student = student
navigationController.pushViewController(nextController, animated: true)


my expectation here is that the value should pass to the tabbarviewcontroller.

My plan was to get the data to the tab bar view controller and when I have an array of view controllers say

HomeFeedViewController
ProfileViewController
SearchUserViewController
HistoryViewController
AddFriendViewController

i could create a student variable for each one of these view controller objects and pass the data from the tab bar view controller.

However, when I try to pass the object from loginViewcontroller to the tabbarviewcontroller, the properties are always nil.

here are some things I've gathered

  • From what I know this has nothing to do with the student object I created. I created a dummy string variable and tried to pass it, however, it was still nil.

  • I suspect that the problem lies within the fact that I am not too familiar with tabbarviewcontrollers since this is the first time I am working on them.




Answered by OOPer in 666623022
Unfortunately viewDidLoad() may not be a good place to use passed values between view controllers.

Please try this code:
Code Block
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .cyan
let randomStr = "dracarys"
let nextController = TabBarViewController()
print("TabBarViewController.init() finished")
nextController.str = randomStr
navigationController?.pushViewController(nextController, animated: true)
}
}
class TabBarViewController : UITabBarController {
var str: String? {
didSet {
debugPrint("TabBarViewController.set:str", str ?? "value is nil")
if let vc1 = self.viewControllers?[0] as? ViewController1 {
vc1.str = str
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
let one = ViewController1()
self.viewControllers = [one, ViewController2()]
debugPrint("TabBarViewController.viewDidLoad", str ?? "value is nil")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
debugPrint("TabBarViewController.viewWillAppear", str ?? "value is nil")
}
}
class ViewController1 : UIViewController {
var str: String?
override func viewDidLoad() {
super.viewDidLoad()
debugPrint("ViewController1.viewDidLoad", str ?? "value is nil")
view.backgroundColor = .red
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
debugPrint("ViewController1.viewWillAppear", str ?? "value is nil")
}
}
class ViewController2 : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
debugPrint("ViewController2.viewDidLoad")
view.backgroundColor = .orange
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
debugPrint("ViewController2.viewWillAppear")
}
}


I assume you mean some subclass of UITabBarController by tabbarviewcontroller.

my expectation here is that the value should pass to the tabbarviewcontroller. 

Embedding a UITabBarController into a UINavigationConroller is not a recommended UI design, but the code you have shown should work as the value should pass to the tabbarviewcontroller.

(Assuming the UI is built programmatically also with your tabbarviewcontroller.)

However, when I try to pass the object from loginViewcontroller to the tabbarviewcontroller, the properties are always nil.

How have you checked it?
Hello thank you for the reply.

I basically put a breakpoint inside viewdidload and checked the values.
here's a basic yet completed code.

Code Block
class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .cyan
    let randomStr = "dracarys"
    sleep(3)
    let nextController = TabBarViewController()
    nextController.str = randomStr
    navigationController?.pushViewController(nextController, animated: true)
  }
}
class TabBarViewController : UITabBarController {
   
  var str: String?
   
  override func viewDidLoad() {
    super.viewDidLoad()
    debugPrint(str ?? "value is nil")
    let one = view1()
    one.str = self.str
    self.viewControllers = [one, view2()]
  }
}
class view1 : UIViewController {
   
  var str: String?
   
  override func viewDidLoad() {
    super.viewDidLoad()
    debugPrint(str ?? "value is nil")
    view.backgroundColor = .red
  }
}
class view2 : UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .orange
  }
}


it always prints "value is nil"
Accepted Answer
Unfortunately viewDidLoad() may not be a good place to use passed values between view controllers.

Please try this code:
Code Block
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .cyan
let randomStr = "dracarys"
let nextController = TabBarViewController()
print("TabBarViewController.init() finished")
nextController.str = randomStr
navigationController?.pushViewController(nextController, animated: true)
}
}
class TabBarViewController : UITabBarController {
var str: String? {
didSet {
debugPrint("TabBarViewController.set:str", str ?? "value is nil")
if let vc1 = self.viewControllers?[0] as? ViewController1 {
vc1.str = str
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
let one = ViewController1()
self.viewControllers = [one, ViewController2()]
debugPrint("TabBarViewController.viewDidLoad", str ?? "value is nil")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
debugPrint("TabBarViewController.viewWillAppear", str ?? "value is nil")
}
}
class ViewController1 : UIViewController {
var str: String?
override func viewDidLoad() {
super.viewDidLoad()
debugPrint("ViewController1.viewDidLoad", str ?? "value is nil")
view.backgroundColor = .red
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
debugPrint("ViewController1.viewWillAppear", str ?? "value is nil")
}
}
class ViewController2 : UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
debugPrint("ViewController2.viewDidLoad")
view.backgroundColor = .orange
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
debugPrint("ViewController2.viewWillAppear")
}
}


really appreciate the help
how to pass data from UIViewController to TabBrController
 
 
Q