引用项目在viewDidLoad中安全地初始化
本周早些时候我遇到了一个奇怪的错误,并希望跟进,看看如何防止问题的根本原因。
采取下面的代码。
//***************************** //MAINVIEWCONTROLLER CLASS CODE //***************************** //Some event happens that triggers me to want to load up TestViewController. func showViewController(){ var testController = TestViewController() testController.someMethod("Test1") self.navigationController?.pushViewController(testController, animated: true) } //***************************** //TESTVIEWCONTROLLER CLASS CODE //***************************** testView:TestView! override func viewDidLoad(){ super.viewDidLoad() testView = TestView() ... } func someMethod(someData:String){ testView.name = someData //AppCrashes here because testView might be nil. ... }
所以有些方法在TestViewController
有机会通过并创buildtestView
之前被解雇。 我然后得到一个不能解开一个可选的值,因为testView
是零,我正在访问它的属性。
奇怪的是我正在运行的应用程序可能在6个不同的地方做这个确切的事情,5/6工作得很好,但是1/6现在给我这个错误。 我猜是因为viewDidLoad
不能保证在执行someMethod
之前立即触发或完成,但是为什么在所有6个用例中都不会发生这种情况。
所以我的主要问题是:
- 为什么这个崩溃发生?
- 避免它的最佳做法是什么?
谢谢! 周到的答案将一如既往地起来票! 让我知道如果有更多的信息会有所帮助。
基本上从不运行源代码控制器中涉及UI元素的目标控制器中的代码。 创build一个属性,将其设置在源控制器中,并将值分配给目标控制器的viewDidLoad()
中的UI元素,例如:
//***************************** //MAINVIEWCONTROLLER CLASS CODE //***************************** //Some event happens that triggers me to want to load up TestViewController. func showViewController(){ var testController = TestViewController() testController.someData = "Test1" self.navigationController?.pushViewController(testController, animated: true) } //***************************** //TESTVIEWCONTROLLER CLASS CODE //***************************** testView:TestView! var someData = "" override func viewDidLoad(){ super.viewDidLoad() testView = TestView() testView.name = someData ... }
当ViewController完成加载以准备显示时,例如当一个segue发生或当一个礼物被包含时,viewDidLoad被调用。
正如你写的代码甚至不应该编译,因为testView是可选的,但你有两个select。 使用可选项(在这种情况下,视图可能不会在viewDidLoad之后调用,但不会崩溃)或存储传递的信息,并将视图更新到viewDidLoad或viewWillAppear中。
你可能想要知道的是viewIfLoaded
你可以用下面的方法强制viewDidLoad方法:
var testViewController = TestViewController() _ = testViewController.view testViewController.someMethod("Test")
初始化ViewController不会自动调用viewDidLoad