Swift - ?和!的学习
最近在优化一个项目的过程,过程中发现之前开发时由于刚接触 Swift
的原因,在 Swift
中的类里使用了很多 OC
的写法,比如字典数组对象会习惯性用 NSDictionary
、NSArray
来初始化,而不是用 [KeyType: ValueType]()
或是 [SomeType]()
这种类型来实例化变量。虽然在使用上没有什么问题,但看起来多少有点。。。不优雅。
当我把大部分类型都修改成 Swift
中的写法后(部分未修改是因为使用 String
类型来给文本做截取和富文本定义,实在不如 NSString
顺手,这种不顺手让我不由想起 Stack Overflow 上看到的一个评论:I thougt i already getting along well with Swift.)发现,原来一些变量是否为空的判断中,使用 Swift
里的 optional
类型会方便很多。
比如解析一个 json 数据,如果层级多而且里面每个元素都是不确定的,那么可能就需要每个层级都判一次空。而如果使用 ? 来设置当前对象为可选值,只需要在最后一层实际使用到对象值时,判一次空就 OK 了。
对于 ? 和 ! 的区别和总结,网上有很多文章,在这里就不重复造轮子了。下面就对这个 optional
的自己两个疑问做个记录。
? 和 ! 是表示两种不同的类型吗,一种是可以为空,一种不可以为空?
刚开始使用的时候没做深入了解,以为 optional
中的 ? 和 ! 和 let
声明不可变变量,var
声明可变变量。? 和 ! 是一组彼此相对只是含义不同的两个符号。但深入了解了一下,发现并不是这样,引用两段官方的文档:
You use the Optional type whenever you use optional values, even if you never type the word Optional. Swift’s type system usually shows the wrapped type’s name with a trailing question mark (?) instead of showing the full type name. For example, if a variable has the type Int?, that’s just another way of writing Optional
. The shortened form is preferred for ease of reading and writing code. The types of shortForm and longForm in the following code sample are the same:
1
2 let shortForm: Int? = Int("42")
let longForm: Optional<Int> = Int("42")
这里的意思是说当你使用 Optional
类型时的值,即使在初始化时没有用“Optional”这个单词指定类型,在 Swift 中也可用 ? 代替。即 Int?
等于 Optional<Int>
。那按照之前我的理解,是否 ! 也是某个 Not Optional 单词的代替?后面官方文档就有提到了:
When you’re certain that an instance of Optional contains a value, you can unconditionally unwrap the value by using the forced unwrap operator (postfix !). For example, the result of the failable Int initializer is unconditionally unwrapped in the example below.
意思是说 ! 是代表一种 Unconditional Unwrapping
的运算符,而并不是作为一种类型的表达。
关于 Unconditional Unwrapping
Unconditional Unwrapping
怎么理解,直译的话叫无条件展开,专业术语叫强制拆包。为什么使用 Optional
类型会需要强制拆包,如果使用 ! 运算符意味着强制拆包,那不使用 ! 时,Optional
是否还会做拆包的处理呢?
仍然回到官方文档,有这句:
The Optional type is an enumeration with two cases. Optional.none is equivalent to the nil literal.
也就是说 Optional
是一个默认带有 Optional.none
枚举类型的包装。所以使用时我们必须按官方说的:
You must unwrap the value of an Optional instance before you can use it in many contexts.
其他
基于以上的学习和理解,我们可以来解读以下一些写法:
1 | let value:NSString = nil //错误写法,未指定 Optional,所以不可以被赋值为空 |
1 | let array:NSArray = NSMutableArray.init(object: "111") |
1 | //可传空值 |
1 | let fruitDic: [String: String] = ["apple":"red","banana":"yellow"] |