swift – 为什么要创建“Implicitly Unwrapped Optionals”,因为这意味着你知道它有价值?

你为什么要创建一个“Implicitly Unwrapped Optional”来创建一个常规变量或常量?如果您知道它可以成功解开,那么为什么要首先创建一个可选项呢?例如,为什么这样:

let someString: String! = "this is the string"

会比以下更有用:

let someString: String = "this is the string"

如果“optionals指示常量或变量允许’没有值’”,但“有时从程序的结构中可以清楚地看出,在首次设置该值之后,可选的值总是会有一个值”,那么有什么意义呢?首先让它成为一个可选项?如果你知道一个可选项总是会有一个值,那不是因为它不是可选的吗?


考虑一个对象在构造和配置时可能具有nil属性的情况,但之后是不可变的和非零的(NSImage通常以这种方式处理,尽管在它的情况下它有时仍然有用)。隐式解包的期权会清理其代码,安全性相对较低(只要保证一个保证,就会安全)。

(编辑)尽管如此:常规选项几乎总是可取的。


在我描述Implicitly Unwrapped Optionals的用例之前,您应该已经了解了Swift中的Optionals和Implicitly Unwrapped Optionals。如果你不这样做,我建议你先阅读我关于期权的文章

何时使用隐式解包的可选项

创建Implicitly Unwrapped Optional有两个主要原因。所有这些都与定义一个永远不会被访问的变量有关,nil否则,Swift编译器将始终强制您显式展开Optional。

1.初始化期间无法定义的常量

初始化完成时,每个成员常量必须具有值。有时,在初始化期间无法使用正确的值初始化常量,但仍可保证在访问之前具有值。

使用Optional变量解决了这个问题,因为Optional会自动初始化,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的断言。即使这样,打开可选项通常也是好的,如果它是零,则使用更具描述性的断言。

何时不使用隐式解包可选

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.其他地方

在大多数情况下,应该避免使用Implicitly Unwrapped Optionals,因为如果误用,整个应用程序在访问时会崩溃nil。如果您不确定变量是否为nil,则始终默认使用普通的Optional。展开一个永远nil不会造成伤害的变量。

添加评论

友情链接:蝴蝶教程