在此示例中使用隐式展开的可选项有什么意义?

时间:2016-01-28 16:28:21

标签: ios swift initializer failable

这是来自文档,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)")
}

这描述如下:

  

在上面的示例中,Product类的name属性是   定义为具有隐式展开的可选字符串类型   (串!)。因为它是可选类型,这意味着名称   property在分配特定值之前的默认值为nil   初始化期间的值。此默认值nil依次表示   Product类引入的所有属性都有   有效的初始值。因此,适用于Product的初始化程序   可以在初始化程序启动时触发初始化失败   如果在为特定值分配之前传递空字符串   初始化程序中的name属性。

看看最后一句:

  

因此,产品的可用初始化程序   可以在初始化程序启动时触发初始化失败   如果在为特定值分配之前传递空字符串   初始化程序中的name属性。

从提供的代码中看不到这一点。在提供的代码中,可以看出赋值发生在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属性进行任何赋值之前触发初始化失败。

1 个答案:

答案 0 :(得分:3)

您对误导性文档的所有疑虑都是正确的。

此外,请注意,在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

  

在类中,允许在初始化所有存储的属性并调用init?()之前退出指定的初始化程序(可以是init() throws)或抛出(super.init())。支持此行为,使指定的初始化程序与便捷初始化程序更加一致。在执行self.init()委派之前,便捷初始化程序也可能失败。