被 Swift 的!和?搞死了😡😡😡

2015-09-07 11:34:46 +08:00
 machinemxy

其实我到现在也还没有理解他们具体应该用在什么场合下,教科书的解释都比较繁杂。于是我在写程序的时候常常遇到红色警报,修改建议让我加个“!”,但是加上后它又抱错建议我删除“!”。真是不明白“?”和“!”存在的意义啊,明明其他语言都没见过这样的语法。

3960 次点击
所在节点    iDev
14 条回复
dorentus
2015-09-07 12:12:47 +08:00
在 Swift 里面,关于 Optional 的 ? 和 ! 有以下几种用法:
1 ) 用于类型定义, Type? 其实是 Optional<Type> 的简写,而 Type! 是一种特殊的 Optional 类型( Implicitly Unwrapped Optional )的写法
2 ) ! 用于 Optional 类型变量名的后缀,用于强行解包(失败则触发 runtime error )
3 ) ? 用于 Optional Chaining ,也是解包,不过失败的话不会触发 runtime error

--------

假设 A 是一个类型,那么 A? 类型(其实是 Optional<A>),其实是一个新的类型,它封装了两种可能性: nil 或者 A 的一个实例。

使用 A? 类型的变量的时候(例如 var a: A?),需要进行判断来解出其中封装的 A 的一个实例值,或者 nil 。解包有好几种方式:
1 ) 直接解,用叹号: let b = a!。如果 a 是 nil 的话,会触发 runtime error
2 ) Optional Binding : if let b = a { /* 这里是有值的情况, b 的类型是 A */ } else { /* 这里是 nil 的情况 */ }
3 ) Optional Chaining : a?.foo () /* 假设 A 定义了 func foo () -> B */,这时假如 a 是 nil ,那么方法调用不会发生;否则的话,方法 foo 被调用,返回一个 Optional<B> 即 B? 的类型的值。

有一些情况,我们明确知道某个变量在我们使用的时候一定非 nil ,但是由于某些限制,无法在声明的时候就初始化(例如 ViewController 里面的 IBOutlet ),那么可以把它声明为 Implicitly Unwrapped Optional 类型,即: var a: A!。对于这种,我们可以像对待 A? 类型的变量一样,去做 Optional Binding 或者 Optional Chaining ,也可以把它当作非 Optional 的 A 类型变量一样直接用(但是如果在用的时候 a 是 nil ,那么会触发 runtime error )

另外,不要在自己不确定在做什么的前提下去理会修改建议
machinemxy
2015-09-07 12:32:07 +08:00
@dorentus 谢谢您耐心的解答。?我已经理解了。关于!,根据您的解答,我的理解是它有两种用法。
第一种是 let b = a! 就是将原本是 A?类型的变量 a 赋值给 b ,然后根据类型推断, b 成为了 A 类型(而不是 A?)。
第二种是 let a = A!,这样定义的话, a 就既可以像 A 类型那样使用,又可以像 A?类型这样使用了。
不知我的理解是否有误。
dorentus
2015-09-07 12:52:33 +08:00
@machinemxy
假如 a 是 A?; let b = a! 的话,其实 b 是 A! 类型。

let a: A! 来定义的话,这个 a 直接就是 A! 类型。

A! 类型的变量,在用的时候可以不解包直接当成和 A 类型的一样用(但是如果值是 nil 的话就直接闪退了)。然后它也可以当作 A? 类型那样,去手动使用 Optional Binding 或者 Chaining 来解包去判断它是 nil 还是有值。
dorentus
2015-09-07 12:59:15 +08:00
@dorentus
我弄错了

直接 let b = a! 解包的话,这个 b 确实是 A 类型了(如果 a 是 nil 的话,出错是在 b 被赋值之前发生的)
machinemxy
2015-09-07 13:11:16 +08:00
@dorentus 多谢,多亏了你,我才弄懂了这几个概念。
fhefh
2015-09-07 13:34:42 +08:00
mark 学习了~
Majirefy
2015-09-07 13:39:34 +08:00
学习学习,的确也不太懂~~
Bijiabo
2015-09-07 14:16:25 +08:00
学习>_<
lk920724
2015-09-07 14:18:55 +08:00
wezzard
2015-09-07 14:22:42 +08:00
忠告:不要面向黑盒子編程
machinemxy
2015-09-07 14:34:24 +08:00
@lk920724 噗…
XueSeason
2015-09-07 22:40:32 +08:00
@wezzard 然而不久 Swift 就开源了。
wezzard
2015-09-08 07:28:07 +08:00
@XueSeason 我說的面向黑盒子編程是指不看編程語言說明書,不搞清楚機制,根據 IDE 的提示來編程。
DingSoung
2015-09-17 22:12:55 +08:00
还好吧 ,我解析 XML 时被 try catch 整了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/218805

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX