安全地引用viewDidLoad中初始化的项目

时间:2017-05-12 22:46:59

标签: ios swift 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.
    ...
}

所以someMethodTestViewController有机会通过并创建testView之前就被解雇了。然后我得到一个无法打开可选值的值,因为testView是nil并且我正在访问它上面的属性。

奇怪的是我正在运行的应用程序可能在6个不同的地方做了这个确切的事情,并且5/6工作得很好,但是1/6现在给了我这个错误。我猜它是因为viewDidLoad不能保证在执行someMethod之前立即启动或完成启动,但为什么在所有6个用例中都没有发生这种情况。

所以我的主要问题是:

  1. 为什么会发生这种崩溃?
  2. 避免它的最佳做法是什么。
  3. 谢谢!周到的答案将一如既往地起床!如果有更多信息有用,请告诉我。

3 个答案:

答案 0 :(得分:1)

当ViewController完成加载以准备显示时,调用viewDidLoad,例如,当发生segue或参与礼物时。

由于编写代码甚至不应编译,因为testView是可选的,但您有两个选择。使用选项(在这种情况下,如果未在viewDidLoad之后调用,视图可能无法获取信息,但它不会崩溃)或存储传递的信息并在viewDidLoad或viewWillAppear中更新视图。

您可能想要注意的是viewIfLoaded

答案 1 :(得分:1)

您可以使用with:

强制viewDidLoad方法

var testViewController = TestViewController() _ = testViewController.view testViewController.someMethod("Test")

初始化ViewController不会自动调用viewDidLoad

答案 2 :(得分:1)

基本上从不在源控制器调用的目标控制器中运行涉及UI元素的代码。创建属性,在源控制器中设置它,并将值分配给目标控制器的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
    ...
}