为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

iOS
幕布斯6054654 2019-12-12 14:10:29
在《 Swift编程语言》(Apple书)中,我读到可以用两种方式创建可选变量:使用问号(?)或使用感叹号(!)。区别在于,当使用(?)获取可选值时,每次需要该值时都必须使用感叹号:var str: String? = "Question mark?"println(str!) // Exclamation mark neededstr = nil    使用(!)时,您可以不带后缀:var str: String! = "Exclamation mark!"println(str) // No suffix neededstr = nil有什么区别?如果根本没有区别,为什么有2种方法呢?
查看完整描述

3 回答

?
慕工程0101907

TA贡献1887条经验 获得超5个赞

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


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页给出了一个示例。


摘要:

采用 ?如果该值将来可能变为nil,以便对此进行测试。

采用 !如果将来它真的不应该变为零,但是最初需要为零。



查看完整回答
反对 回复 2019-12-13
?
慕的地8271018

TA贡献1796条经验 获得超4个赞

您应该超越语法糖。


有两种完全不同的多态类型。语法糖仅使用这些类型中的一种或另一种。


当你Foo?以类型写作时,你确实拥有Optional<Foo>,而当你写作时,Foo!你确实具有ImplicitlyUnwrappedOptional<Foo>。


这是两种不同的类型,它们也有所不同Foo。



查看完整回答
反对 回复 2019-12-13
?
料青山看我应如是

TA贡献1772条经验 获得超8个赞

?(可选)表示您的变量在

!时可能包含nil值。(解包器)表示在运行时使用变量(尝试从中获取值)时,变量必须具有内存(或值)。


主要区别在于,当可选值为nil时,可选链接会正常失败,而当可选值为nil时,强制展开会触发运行时错误。


为了反映可以在nil值上调用可选链接的事实,即使要查询的属性,方法或下标返回非可选值,可选链接调用的结果也始终是可选值。您可以使用此可选返回值来检查可选链接调用是否成功(返回的可选包含一个值),或者由于链中的值为nil而失败(返回的可选值为nil)。


具体来说,可选链接调用的结果与预期返回值的类型相同,但包装在可选中。通常返回Int的属性将返回Int?通过可选链访问时。


var defaultNil : String?  // declared variable with default nil value

println(defaultNil) >> nil  


var canBeNil : String? = "test"

println(canBeNil) >> optional(test)


canBeNil = nil

println(canBeNil) >> nil


println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper


var canNotBeNil : String! = "test"

print(canNotBeNil) >> "test"



var cantBeNil : String = "test"

cantBeNil = nil // can't do this as it's not optional and show a compile time error



查看完整回答
反对 回复 2019-12-13
  • 3 回答
  • 0 关注
  • 461 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信