在我描述隐式解包选项的用例之前,您应该已经了解 Swift 中的选项和隐式解包选项是什么。如果你不这样做,我建议你先阅读我关于选项的文章 http://www.drewag.me/posts/what-is-an-optional-in-swift
何时使用隐式解包可选
创建隐式解包可选有两个主要原因。所有这些都与定义一个永远不会被访问的变量有关nil
因为否则,Swift 编译器将始终强制您显式解开一个Optional。
1. 初始化时无法定义的常量
在初始化完成时,每个成员常量都必须有一个值。有时,常量在初始化时无法用正确的值进行初始化,但仍然可以保证在访问之前它有一个值。
使用可选变量可以解决此问题,因为可选变量会自动初始化为nil
并且它最终包含的值仍然是不可变的。然而,不断地解开一个你确信不为零的变量可能会很痛苦。隐式解包的Options 实现了与Optional 相同的好处,但额外的好处是不必在任何地方显式地解包它。
一个很好的例子是,在加载视图之前,无法在 UIView 子类中初始化成员变量:
class MyView: UIView {
@IBOutlet var button: UIButton!
var buttonOriginalWidth: CGFloat!
override func awakeFromNib() {
self.buttonOriginalWidth = self.button.frame.size.width
}
}
在这里,在视图加载之前您无法计算按钮的原始宽度,但您知道awakeFromNib
将在视图上的任何其他方法(初始化除外)之前调用。您可以将其声明为隐式解包可选,而不是强制在整个类中毫无意义地显式解包该值。
2. 当你的应用程序无法从变量中恢复时nil
这应该是极其罕见的,但是如果你的应用程序无法继续运行,如果变量是nil
当访问时,费心测试它是浪费时间nil
。通常,如果您的应用程序必须满足一个条件才能继续运行,那么您将使用assert
。隐式解包可选有一个内置的 nil 断言。即使如此,如果它为 nil,最好解开可选值并使用更具描述性的断言。
何时不使用隐式解包可选
1. 延迟计算成员变量
有时你有一个不应该为 nil 的成员变量,但在初始化期间无法将其设置为正确的值。一种解决方案是使用隐式解包可选,但更好的方法是使用惰性变量:
class FileSystemItem {
}
class Directory : FileSystemItem {
lazy var contents : [FileSystemItem] = {
var loadedContents = [FileSystemItem]()
// load contents and append to loadedContents
return loadedContents
}()
}
现在,成员变量contents
直到第一次访问时才初始化。这使类有机会在计算初始值之前进入正确的状态。
Note:这似乎与上面的#1 相矛盾。然而,有一个重要的区别需要做出。这buttonOriginalWidth
上述必须在 viewDidLoad 期间设置,以防止任何人在访问该属性之前更改按钮宽度。
2. 其他地方
在大多数情况下,应该避免隐式解包选项,因为如果使用错误,整个应用程序将在访问时崩溃nil
。如果您不确定变量是否可以为零,请始终默认使用普通的Optional。解开一个永远不会存在的变量nil
当然不会很痛。