【问题标题】:Swift UIViewController subclass instance variable initialization strategySwift UIViewController 子类实例变量初始化策略
【发布时间】: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


【解决方案1】:

您使用隐式解包的可选项很好,因为您使用的是隐式解包的可选项,所以没有什么可以阻止您在使用它之前检查可选项是否为 nil。

如果变量为 nil,则在函数顶部设置一个保护语句以提前退出。

【讨论】:

  • 但这需要在每个函数中设置一个保护语句......在这种情况下,我不妨使用相同的保护语句来打开一个可选的。我希望在需要防范的一两个地方有一个最佳实践,然后从那时起我就不必担心了。
  • 车辆在视图控制器中来自哪里?视图控制器在没有车辆的情况下存在意味着什么?如果视图控制器在没有车辆的情况下根本没有任何意义,那么您可能应该设置它,以便传递车辆以构造视图控制器。如果视图控制器没有载具是有意义的,那么当它不存在时,您应该明确处理这种情况。
  • 视图控制器没有车辆存在的地方。因此,我同意(希望很少见)可能为零的情况需要明确处理......因此首先提出问题的目的是:Swift 社区针对这种情况采用的最佳实践是什么?我知道我可以将其设为可选并在任何地方进行检查,但这样做非常痛苦,我猜有人想出了更好的模式。
  • 隐式展开的可选更好的模式。如果您想检查某个地方,那么我建议viewWillAppear,因为如果此时它没有值,您可能无法正确显示内容,但这是错误的结果- 例如,您没有在prepareForSegue 中正确设置。在这种情况下,崩溃会准确地告诉你测试期间发生了什么,让你修复错误并继续前进
  • 是的,我考虑过在viewWillAppear 中设置一个 nil 检查,但它不是在某些情况下(例如 UITableViewControllers)被调用的第一个委托。在这些情况下,首先调用的似乎是tableView: numberOfRowsInSection。在这种情况下,我可能只是将支票放在两个地方,然后就结束了。只是希望有更好的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多