今天下午,我提交了基于 Swift 3.0 的奇点 2.1.1 版本,主要是适配了 Swift 3.0 + 一些 Bug 修复。在适配 Swift 3.0 的过程中,我记录了一些常见的问题,相信所有在适配过程中的朋友都会遇到,于是总结这么一篇文章分享一下。
奇点项目是一个小型的纯 Swift 的 iOS 项目,十余个第三方库 + 超两万行代码。它是我在 2014 年一开始就接触 Swift 以来的一个 Objective-C 项目用 Swift 重写的实验作品,后来把它做成了产品推出来。所以它存在的价值之一就是为了适配新一代 Swift 😂
所以 Swift 3.0 出来后,我咬咬牙,就决定立即开始适配它了。大概花了约一个晚上+一个白天的时间我就完成了对适配工作,同时淘汰了一些不兼容 Swift 3 的三方库,可以说是神清气爽。
那么下面我就开始一一列举适配 Swift 工作中遇到的问题和一些新习得的概念吧。
将项目里的 AnyObject 转成 Any 可能是大家遇到的第一件适配大事。如何解释这个变化呢?在 Swift 3 之前,我们可以写完一个项目都只用 AnyObject 来代表任何类型,几乎不用与 Any 类型打交道。在 Swift 3 当中,你会发现你不得不与 Any 类型打交道了。这是因为 Swift 3 针对 Any 和 AnyObject 做了更清晰的定义:Any 可以代表 struct、class、func 等等几乎所有类型,而 AnyObject 只能代表 class 生成的实例。
有了这句话,一切就比较好理解了。一个 String 实例是 Any,而 NSString 的实例是 AnyObject。Int、Tuple、func(closure)等等也都是 Any。
所以何时用 Any 何时用 AnyObject 就显而易见了。常见的情况下,我们在遇到 struct 时用 Any,class 时用 AnyObject 即可。
在 Swift 3 编译器下,如果一个 func 返回了一个对象,而你没有使用它时,会有一个 WARNING。对于追求项目洁癖(不想看到 1 个 WARNING 和 1 个 ERROR)的人来说这是不能忍的,尽管你可能是故意不去使用它的。
这里有两种方法可以解决这个 WARNING。
第一种:在 func 定义的前面,加上 @discardableResult 的修饰符,代表可以不使用返回值,这样编译器就不会有警告了。在我们自己定义的 func 上基本上都可以这么做。
但是还会有一种情况,用了第三方库或者系统库返回的对象怎么办?那只能用第二种办法:
_ = navigationController?.popViewController(animated: true)
像这样通过 _ 来省略掉了。虽然比较难看,考虑到 Swift 是一门严格的语言,就忍忍吧。
以前写代码时会有不注意的地方,比如 UITableViewDelegate 和 UITableViewDataSource,我分别用 extension 来实现,但是在具体的实现中没注意,把 delegate 的一个方法放进了 dataSource 的 extension 去实现,项目也能完全正常运作。
但是在 Swift 3.0 下,如果你在一个 extension 里实现一个 protocol,那么这个 protocol 的方法一定要在这个 extension 里面能找到,而不能在另外一个 extension 里或者主 class 或 struct 里面。不然会有类似这样的警告:
Objective-C method 'tableView:canEditRowAt:' provided by method 'tableView(_:canEditRowAt:)' does not match the requirement's selector ('tableView:canEditRowAtIndexPath:')
这也是 Swift 3 编译变得更严格的一个表现。
在 Swift 2 的项目中,我们可能存在这样不是特别安全的代码:
var greetings: String!
greetings = "Hello"
print("\(greetings) 图拉鼎")
这里会输出:
Hello 图拉鼎
没有任何问题。但是在 Swift 3 中,因为 Optional 的安全机制起作用了,会变成:
Optional("Hello") 图拉鼎
这个结果不是我们想要的。从这点也可以看到,Swift 3 的 IUO 行为变得更安全了,默认会把 IUO 变成 Optional。如果想要达到和 Swift 2 一样的效果,就得用:
print("\(greetings!) 图拉鼎")
这时你也注意到了,Swift 始终在用 ! 提醒你用 IUO 不那么安全。
所以趁这个机会可以好好重构一下老代码吧~
如果你是用 Xcode 的自动转换器来转 Swift 3 项目的,应该会遇到一些奇怪的坑,特别举例:
适配完奇点这个两万多行代码的项目后,实际上可以总结的远远不止上面这些,我只是挑了一些典型来讲。更何况,我只是完成了第一步「适配」而已,更多的工作,比如把 API 命名更加 Swift 3 化,充分利用 Swift 3 的一些特性来重构项目等等都还没有做。
所以在接下去的路上,应该还会去总结和学习一些东西吧。祝大家适配 Swift 3 愉快😅
本站架设于 Linode 东京机房,同时使用 云梯 进行科学上网