【发布时间】:2016-07-28 22:19:19
【问题描述】:
我有几个 UIViewController 子类需要一些实例数据集才能正确加载。
例如: - 注意:这是一个人为的例子,如果我错过了一些小细节,请道歉 - 第 2 行是该问题真正需要的唯一部分。
class VehicleSpecificationsTableViewController: UITableViewController {
var vehicle: Vehicle! // <-- Implicitly unwrapped optional is my current solution
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return vehicle.specs.count // <-- Crashes here if the view ever loads/reloads when I'm not expecting it
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("vehicleSpecCell", forIndexPath: indexPath) as? VehicleSpecTableViewCell
cell.spec = vehicle.specs[indexPath.row]
return cell
}
}
问题是这里应该使用哪种类型的变量作为最佳实践。我一直在使用可选项,但是必须在任何地方打开它们是一件很痛苦的事情,所以我正在转换为隐式打开的选项,因为我将在一般加载视图之前设置变量。
问题是我担心控制器有时会在我没有直接意识到它的情况下重新加载(在内存警告、设备旋转、从后台唤醒、任何其他奇怪的边缘情况之后)。虽然我知道这可能不应该发生,但如果我不能 100% 确定它不可能始终为 nil,那么使用隐式展开的可选项似乎仍然很危险。因此,我正在考虑在某处进行检查,以确保在加载之前实际设置了任何隐式展开的变量。
编辑:一个更可能的情况是它为零是几个月后出现第二个开发人员并实现使用我的控制器的东西,并且不知道实例变量需要在加载之前设置。虽然我想他们应该更清楚,但这会导致生产崩溃,而这正是我试图避免的。我希望它不可能在不依赖约定的情况下崩溃(并且希望不在许多/所有函数中检查/解包选项)
到目前为止,我发现将检查放入 viewDidLoad() 为时已晚。我已经尝试将它放在 viewWillAppear() 中,但这不适用于 UITableViewControllers 之类的东西,因为它们会在视图出现之前尝试加载数据。
基本问题是,Swift 社区是否已经确定了最佳实践?是否使用选项并处理展开、隐式展开的选项并处理战略位置的 nil 检查、非选项并将 init() 添加到每个控制器?或者有没有更好的解决方案我还没有遇到过?
任何想法/建议将不胜感激。
【问题讨论】:
-
我使用隐式展开的选项和测试。您可以检查 nil 的可选项,但您要做什么?如果它突然为零,您的应用程序可能无法继续。您可以记录某种错误消息,但测试/开发期间的异常更有用。除非重新启动整个应用程序,否则无法重新加载视图控制器。 iOS 可以向您发送内存不足警告,但不会随意从内存中删除内容,除非它会杀死您的整个应用程序;并且只会在您的应用暂停时发生
-
在许多情况下,有问题的控制器已被绑定到导航控制器堆栈并且位于导航控制器堆栈的顶部,因此将其恢复为 nil 是为了向用户显示出现问题的警报,并且然后将控制器从堆栈中弹出。它不能解决任何导致它进入 nil 状态的问题,但它不会崩溃,这是最重要的。
标签: ios swift optional instance-variables unwrap