简体   繁体   English

将数据从 UIViewController 传递到 UITabBarController 始终为零

[英]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.这是简单的代码,有一个视图 controller 并将一些字符串数据从我拥有的值传递给 uitabbarcontroller 应该打印出来,但它总是为零。

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. UI 是编程编码的,所以没有涉及故事板我总是得到价值为零,我还没有能够解决这个问题。

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."你是说,在第二个代码中:“当这个代码运行时,我的str已经被第一个代码设置(到randomStr或其他)。”

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.然后self.str最终会为零。 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.您假设在该代码运行之前设置了视图控制器的str 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苹果开发者论坛的功劳归于 OOPer

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我的问题是在 viewdidload 检查东西

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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