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