Swift隐式解包 Optional
相对于普通的 Optional 值,在 Swift 中我们还有一种特殊的 Optional,在对它的成员或者方法进行访问时,编译器会帮助我们自动进行解包,这就是 ImplicitlyUnwrappedOptional。在声明的时候,我们可以通过在类型后加上一个感叹号 (!) 这个语法糖来告诉编译器我们需要一个可以隐式解包的 Optional 值:
var maybeObject: MyClass!
首先需要明确的是,隐式解包的 Optional 本质上与普通的 Optional 值并没有任何不同,只是我们在对这类变量的成员或方法进行访问的时候,编译器会自动为我们在后面插入解包符号 !,也就是说,对于一个隐式解包的下面的两种写法是等效的:
var maybeObject: MyClass! = MyClass() maybeObject!.foo() maybeObject.foo()
我们知道,如果 maybeObject 是 nil 的话那么这两种不加检查的写法的调用都会导致程序崩溃。而如果 maybeObject 是普通的 Optional 的话,我们就只能使用第一种显式地加感叹号的写法,这能提醒我们也许应该使用 if let 的 Optional Binding 的形式来处理。而对隐式解包来说,后一种写法看起来就好像我们操作的 maybeObject 确实是 MyClass 类的实例,不需要对其检查就可以使用 (当然实际上这不是真的)。为什么一向以安全著称的 Swift 中会存在隐式解包并可以写出让人误认为能直接访问的这种危险写法呢?
一切都是历史的错。因为 Objective-C 中 Cocoa 的所有类型变量都可以指向 nil 的,有一部分 Cocoa 的 API 中在参数或者返回时即使被声明为具体的类型,但是还是有可能在某些特定情况下是 nil,而同时也有另一部分 API 永远不会接收或者返回 nil。在 Objective-C 时,这两种情况并没有被加以区别,因为 Objective-C 里向 nil 发送消息并不会有什么不良影响。在将 Cocoa API 从 Objective-C 转为 Swift 的 module 声明的自动化工具里,是无法判定是否存在 nil 的可能的,因此也无法决定哪些类型应该是实际的类型,而哪些类型应该声明为 Optional。
在这种自动化转换中,最简单粗暴的应对方式是全部转为 Optional,然后让使用者通过 Optional Binding 来判断并使用。虽然这是最安全的方式,但对使用者来说是一件非常麻烦的事情,我猜不会有人喜欢每次用个 API 就在 Optional 和普通类型之间转来转去。这时候,隐式解包的 Optional 就作为一个妥协方案出现了。使用隐式解包 Optional 的最大好处是对于那些我们能确认的 API 来说,我们可直接进行属性访问和方法调用,会很方便。但是需要牢记在心的是,隐式解包不意味着 “这个变量不会是 nil,你可以放心使用” 这种暗示,只能说 Swift 通过这个特性给了我们一种简便但是危险的使用方式罢了。
另外,其实在 Apple 的不断修改 (我相信这是一件消耗大量人月的手工工作) 下,在 Swift 的正式版本中,已经没有太多的隐式解包的 API 了。最近 Objective-C 中又加入了像是 nonnull 和 nullable 这样的修饰符,这样一来,那些真正有可能为 nil 的返回可以被明确定义为普通的 Optional 值,而那些不会是 Optional 的值,也根据情况转换为了确定的类型。现在比较常见的隐式解包的 Optional 就只有使用 Interface Builder 时建立的 IBOutlet 了:
@IBOutlet weak var button: UIButton!
如果没有连接 IB 的话,对 button 的直接访问会导致应用崩溃,这种情况和错误在调试应用时是很容易被发现的问题。在我们的代码的其他部分,还是少用这样的隐式解包的 Optional 为好,很多时候多写一个 Optional Binding 就可以规避掉不少应用崩溃的风险。
建议继续学习:
- OpenStack Swift源码导读之——业务整体架构和Proxy进程 (阅读:2952)
- 你应该更新的Java知识之Optional (阅读:2203)
- Openstack Swift简介 (阅读:1825)
- Swift 性能探索和优化分析 (阅读:2031)
- 自己动手使用 Swift 打造全功能 JSON 解析、生成库 (阅读:1289)
- Swift ABI 稳定对我们到底意味着什么 (阅读:1083)
- Swift的多重 Optional (阅读:961)
- Swift错误和异常处理 (阅读:948)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:王巍 (@onevcat) 来源: Swifter
- 标签: Optional Swift
- 发布时间:2016-01-27 22:41:02
- [70] IOS安全–浅谈关于IOS加固的几种方法
- [69] Twitter/微博客的学习摘要
- [64] 如何拿下简短的域名
- [63] Go Reflect 性能
- [63] android 开发入门
- [61] find命令的一点注意事项
- [59] 流程管理与用户研究
- [58] Oracle MTS模式下 进程地址与会话信
- [58] 读书笔记-壹百度:百度十年千倍的29条法则
- [58] 图书馆的世界纪录