简体   繁体   中英

passing data from UIViewController to UITabBarController is always nil

here's the simple code there is a view controller and passes some string data to a uitabbarcontroller from what I have the value should be printed out however it is always nil.

i tried convenience init however result was the same

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

UI is programatically coded so, there are no storyboards involved I always get value is nil and I have not yet been able to resolve this probelm.

Think about the timing assumption built into this code:

    let nextController = TabBarViewController()
    nextController.str = randomStr

and:

    let one = view1()
    one.str = self.str

You are saying, in that second code: "By the time this code runs, my str has been set (to randomStr or whatever) by the first code."

But what if that's not true? What if

    nextController.str = randomStr

runs later than

    one.str = self.str

?? Then self.str will end up as nil. You need to construct your code in such a way that you make no assumptions about the order in which things will happen, for the simple reason that you have no basis whatever for making any assumptions about that order.

The same thing is true of the next stage of the story:

    debugPrint(str ?? "value is nil")

You are assuming that this view controller's str is set before that code runs. But you do not know that either, Again, this code needs to be bullet-proofed against assumptions about the order in which things will happen.

finally after searching for a while I was able to get it to working. the credit goes to OOPer from apple developer forums

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")
    }
}

my problem was checking things at viewdidload

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM