引用项目在 viewDidLoad 中安全地初始化
Referencing item's initialized in viewDidLoad safely
我 运行 本周早些时候遇到了一个奇怪的错误,想跟进以了解如何防止问题的根本原因。
取下面的代码。
//*****************************
//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.
...
}
所以 someMethod
在 TestViewController
有机会通过并创建 testView
之前就被解雇了。然后我得到一个 cannot unwrap an optional value because testView
is nil 并且我正在访问它上面的 属性 。
Whats st运行ge 是我的应用程序 运行 可能在 6 个不同的地方做这件事,5/6 工作得很好,但 1/6 现在给我这个错误。我猜是因为 viewDidLoad
没有被 gua运行teed 立即触发或在 someMethod
执行之前完成,但是为什么这在所有 6 个用例中都没有发生.
所以我的主要问题是:
- 为什么会发生此崩溃?
- 避免它的最佳做法是什么。
谢谢!深思熟虑的答案将一如既往地获得投票!让我知道是否有更多信息会有所帮助。
viewDidLoad 在 ViewController 完成加载准备显示时调用,例如当发生转折或涉及礼物时。
正如所写,您的代码甚至不应该编译,因为 testView 是可选的,但您有两个选择。使用可选项(在这种情况下,如果在 viewDidLoad 之后未调用,视图可能无法获取信息,但它不会崩溃)或存储传递的信息并在 viewDidLoad 或 viewWillAppear 中更新您的视图。
您可能需要注意的是 viewIfLoaded
您可以强制使用 viewDidLoad 方法:
var testViewController = TestViewController()
_ = testViewController.view
testViewController.someMethod("Test")
初始化 ViewController 不会自动调用 viewDidLoad
基本上从不 运行 从源控制器调用的目标控制器中涉及 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
...
}
我 运行 本周早些时候遇到了一个奇怪的错误,想跟进以了解如何防止问题的根本原因。
取下面的代码。
//*****************************
//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.
...
}
所以 someMethod
在 TestViewController
有机会通过并创建 testView
之前就被解雇了。然后我得到一个 cannot unwrap an optional value because testView
is nil 并且我正在访问它上面的 属性 。
Whats st运行ge 是我的应用程序 运行 可能在 6 个不同的地方做这件事,5/6 工作得很好,但 1/6 现在给我这个错误。我猜是因为 viewDidLoad
没有被 gua运行teed 立即触发或在 someMethod
执行之前完成,但是为什么这在所有 6 个用例中都没有发生.
所以我的主要问题是:
- 为什么会发生此崩溃?
- 避免它的最佳做法是什么。
谢谢!深思熟虑的答案将一如既往地获得投票!让我知道是否有更多信息会有所帮助。
viewDidLoad 在 ViewController 完成加载准备显示时调用,例如当发生转折或涉及礼物时。
正如所写,您的代码甚至不应该编译,因为 testView 是可选的,但您有两个选择。使用可选项(在这种情况下,如果在 viewDidLoad 之后未调用,视图可能无法获取信息,但它不会崩溃)或存储传递的信息并在 viewDidLoad 或 viewWillAppear 中更新您的视图。
您可能需要注意的是 viewIfLoaded
您可以强制使用 viewDidLoad 方法:
var testViewController = TestViewController()
_ = testViewController.view
testViewController.someMethod("Test")
初始化 ViewController 不会自动调用 viewDidLoad
基本上从不 运行 从源控制器调用的目标控制器中涉及 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
...
}