【问题标题】:Force unwrap or use optional chaining to set property强制展开或使用可选链接来设置属性
【发布时间】:2018-12-23 00:34:09
【问题描述】:

给定一个可选的 var pinImageView: UIImageView? 已设置属性,我不确定设置属性的首选方式。例如:

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView?.restorationIdentifier = "pin"
}

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView!.restorationIdentifier = "pin"
}

【问题讨论】:

  • 当没有被广泛接受的方式时,首选的答案可以是基于意见的。该网站似乎不适合收集此类意见。
  • Force unwrap(!) 总是不鼓励的,因为它可能会使您的应用程序崩溃。在上面的例子中,虽然pinImageView 是在对它使用强制解包(!)之前初始化的,并且它会在上面两种方法中按预期工作,但我仍然推荐第一种方法。避免习惯于有问题的方法。
  • @OOPer 我怎么能提前知道这个问题是基于意见的?一种方法可能被认为是错误的。
  • 还有第三种选择:if let image = UIImage(named: "Pin"), let view = UIImageView(image: image) { view.restorationIdentifier = "pin" }
  • @Kamran ! 气馁。它有合法的用例。有时您无法以任何其他方式处理此案。声称您的应用不会崩溃而是创建未定义的应用行为并不是一个好主意。此外,我经常看到人们避免使用!,但仍然在他们的代码中添加fatalError()

标签: swift forced-unwrapping optional-chaining


【解决方案1】:

首选哪种方式

大家普遍认为你应该避免! (force unwrapping) 这只是乞求崩溃,所以应该避免这种用法:

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView!.restorationIdentifier = "pin"
}

在这种情况下,由于您刚刚分配了pinImageView,因此强制解开它是安全的,但是它仍然会向您或将来阅读您代码的任何其他人发出危险信号。 “呃,他们在这里使用强制解包。那会崩溃吗?嗯,pinImageView可以是nil吗?不,它只是在上一行中分配的,所以没关系。”为什么要让自己和他人经历这个思考过程?尽可能避免使用!

这种用法:

if let image = UIImage(named: "Pin") {
    pinImageView = UIImageView(image: image)
    pinImageView?.restorationIdentifier = "pin"
}

更安全,因为它使用可选链解开pinImageView并避免崩溃运算符 !,但它仍然解开可选变量。

第三种选择:

imageView 是可选的原因是您已将其分配给可选变量。相反,如果您在配置对象时使用let 常量来保存对象,则可以避免使用展开代码填充代码:

if let image = UIImage(named: "Pin") {
    let imageView = UIImageView(image: image)
    imageView.restorationIdentifier = "pin"
    pinImageView = imageView
}

当您为对象分配许多属性时,此方法效果很好,因为您可以避免许多展开运算符。

不用担心额外的代码行。编译器会优化它。代码的可读性和清晰度。

【讨论】:

  • 当只有一个属性被分配时,你会说第二种可选链接方式很好吗?
  • @bhartsb,没关系。如果只分配一个属性,我可能会这样做。但是当您分配两个或三个时,可选链接开始突出。
【解决方案2】:

我们的团队有一个代码样式/审查规则,类似于“No 使用 ! 操作符,但没有说明其安全性的注释”。

因为!破坏了 Swift 中 nil-safety 的所有优点,随意使用它会导致崩溃并将语言拖回 C/C++/Java/C#/Javascript/etc NullPointerException 地狱。

所以在你的情况下

pinImageView?.restorationIdentifier = "pin"

绝对是首选。

【讨论】:

  • 谢谢,我对接受的解决方案犹豫不决。
猜你喜欢
  • 2022-11-25
  • 1970-01-01
  • 1970-01-01
  • 2015-07-31
  • 1970-01-01
  • 2018-01-10
  • 1970-01-01
  • 2018-05-17
  • 2015-01-03
相关资源
最近更新 更多