在此示例中使用隐式解包可选的意义何在?

What is the point of using implicitly unwrapped optional in this example?

这是来自文档,第 Failable Initializers for Classes 部分:

class Product {

     let name: String!
     init?(name: String) {
           self.name = name
           if name.isEmpty { return nil }
     }
}


if let bowTie = Product(name: "") {
   // no need to check if bowTie.name == nil
   print("The product's name is \(bowTie.name)")
}

描述如下:

In the example above, the name property of the Product class is defined as having an implicitly unwrapped optional string type (String!). Because it is of an optional type, this means that the name property has a default value of nil before it is assigned a specific value during initialization. This default value of nil in turn means that all of the properties introduced by the Product class have a valid initial value. As a result, the failable initializer for Product can trigger an initialization failure at the start of the initializer if it is passed an empty string, before assigning a specific value to the name property within the initializer.

看最后一句:

As a result, the failable initializer for Product can trigger an initialization failure at the start of the initializer if it is passed an empty string, before assigning a specific value to the name property within the initializer.

从提供的代码看不出这一点。在提供的代码中,可以看出在 return nil 部分之前发生了赋值,并且是 String(非可选)或 String? (可选)会起作用。

另一件事是,在提供的示例中,如果它被定义为常量,则使用隐式展开的可选值是没有意义的。必须在 init 完成之前将常量初始化为默认值。

对此有任何想法,或者有人知道不对此提交雷达的原因吗?也许我错过了什么?我实际上有一个想法为什么在这里使用隐式解包可选,但这是一个不好的例子。对我来说,这更有意义:

class Product {

    var name: String! //let is changed to var

    init?(name: String) {

       if name.isEmpty { return nil } //Check here if passed value is non-empty
       self.name = name
    }
}

这样,在对 name 属性.

进行任何赋值之前,可以触发初始化失败

您对误导性文档的所有担忧都是正确的。

此外,请注意,在 Swift 2.2 中,从可失败的初始化程序提前返回 确实有效 ,甚至在所有属性都初始化之前:

class Product {
    let name: String
    init?(name: String) {
        if name.isEmpty { return nil }
        self.name = name
    }
}

另一个变化是当从可失败初始化器返回 nil 时,deinit 不再被调用

来自 Xcode 7.3 beta 2 Release Notes:

Inside a class, a designated initializer that is either failable (init?()) or throwing (init() throws) is allowed to exit before initializing all stored properties and calling super.init(). This behavior is supported, making designated initializers more consistent with convenience initializers. Convenience initializers can also fail before performing a self.init() delegation.