一尘不染

String和有什么不一样?和弦!(创建可选变量的两种方式)?

swift

《 Swift编程语言》 (Apple书)中,我读到可以用两种方式创建可选变量:使用问号(?)或使用感叹号(!)。

区别在于,当使用(?)获得可选值时,每次需要该值时都必须使用感叹号:

var str: String? = "Question mark?"
println(str!) // Exclamation mark needed
str = nil

使用(!)时,您可以不带后缀:

var str: String! = "Exclamation mark!"
println(str) // No suffix needed
str = nil

有什么区别?如果根本没有区别,为什么有2种方法呢?


阅读 200

收藏
2020-07-07

共1个答案

一尘不染

当两个类相互指向并且您需要避免强引用循环时,使用隐式解开的可选变量(用!声明)的真正好处与类初始化有关。例如:

A级<-> B级

A类的初始化例程需要创建(并拥有)B类,而B需要对A的弱引用:

class A {
    let instanceOfB: B!
    init() {
        self.instanceOfB = B(instanceOfA: self)
    }
}

class B {
    unowned let instanceOfA: A
    init(instanceOfA: A) {
        self.instanceOfA = instanceOfA
    }
}

现在,

  • B类需要引用要初始化的A类。
  • A类只有self在完全初始化后才能传递给B类的初始化器。
  • 为了使A类在创建B类之前被视为已初始化,instanceOfB因此该属性必须是可选的。

但是,一旦创建了A,就不得不使用instanceOfB访问instanceOfB!因为我们 知道 必须有一个B

为了避免这种情况,instanceOfB被声明为一个隐式未包装的可选(instanceOfB!),我们可以仅使用instanceOfB对其进行访问。(此外,我
怀疑 编译器也可以不同地优化访问)。

这本书的第464至466页给出了一个示例。

摘要:

  • 用 ?如果该值将来可能变为零,以便对此进行测试。
  • 用 !如果它将来真的不应该变为零,但是最初需要为零。
2020-07-07