适配 Swift 3 的一点小经验和坑

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
查看查看157 回复回复1 收藏收藏 分享淘帖 转播转播 分享分享 微信
查看: 157|回复: 1
收起左侧

适配 Swift 3 的一点小经验和坑

[复制链接]
移动 发表于 2016-10-30 13:02:43 | 显示全部楼层 |阅读模式
快来登录
获取优质的苹果资讯内容
收藏热门的iOS等技术干货
拷贝下载Swift Demo源代码
订阅梳理好了的知识点专辑

昨天下午,我提交了基于 Swift 3.0 的奇点 for 微博 2.1.1 版本,主要是适配了 Swift 3.0 + 一些 Bug 修复。在适配 Swift 3.0 的过程中,我记录了一些常见的问题,相信所有在适配过程中的朋友都会遇到,于是总结这么一篇文章分享一下。

适配 Swift 3 的一点小经验和坑

适配 Swift 3 的一点小经验和坑 - 敏捷大拇指 - 适配 Swift 3 的一点小经验和坑





0、前言

奇点项目是一个小型的纯 Swift 的 iOS 项目,十余个第三方库 + 超两万行代码。它是我在 2014 年一开始就接触 Swift 以来的一个 Objective-C 项目用 Swift 重写的实验作品,后来把它做成了产品推出来。所以它存在的价值之一就是为了适配新一代 Swift。

所以 Swift 3.0 出来后,我咬咬牙,就决定立即开始适配它了。大概花了约一个晚上+一个白天的时间我就完成了对适配工作,同时淘汰了一些不兼容 Swift 3 的三方库,可以说是神清气爽。

那么下面我就开始一一列举适配 Swift 工作中遇到的问题和一些新习得的概念吧。




1、Any vs AnyObject

将项目里的 AnyObject 转成 Any 可能是大家遇到的第一件适配大事。如何解释这个变化呢?在 Swift 3 之前,我们可以写完一个项目都只用 AnyObject 来代表大多数实例,好像不用与 Any 类型打交道。但事实上,Any 和 AnyObject 是有明显区别的,因为 Any 可以代表 struct、class、func 等等几乎所有类型,而 AnyObject 只能代表 class 生成的实例。

那为什么之前我们在 Swift 2 里可以用 [AnyObject] 声明数组,并且在里面放 Int、String 等 struct 类型呢?这是因为 Swift 2 中,会针对这些 Int、String 等 struct 进行一个 Implicit Bridging Conversions,在 Array 里插入他们时,编译器会自动将其 bridge 到 Objective-C 的 NSNumber、NSString 等类型,这就是为什么我们声明的 [AnyObject] 里可以放 struct 的原因。

但在 Swift 3 当中,为了达成一个门真正的跨平台语言,相关提案将 Implicit Bridging Conversions 给去掉了。所以如果你要把 String 这个 struct 放进一个 [AnyObject] 里,一定要 as NSString,这些转换都需要显示的进行了——毕竟 Linux 平台默认没有 Objective-C runtime。这样各平台的表现更加一致。当然这是其中一个目标,具体可见 https://github.com/apple/swift-evolution/blob/master/proposals/0116-id-as-any.md 和相关提案的讨论。




2、@discardableResult 的使用

在 Swift 3 编译器下,如果一个 func 返回了一个对象,而你没有使用它时,会有一个 WARNING。对于追求项目洁癖(不想看到 1 个 WARNING 和 1 个 ERROR)的人来说这是不能忍的,尽管你可能是故意不去使用它的。

这里有两种方法可以解决这个 WARNING。

第一种:在 func 定义的前面,加上 @discardableResult 的修饰符,代表可以不使用返回值,这样编译器就不会有警告了。在我们自己定义的 func 上基本上都可以这么做。

但是还会有一种情况,用了第三方库或者系统库返回的对象怎么办?那只能用第二种办法:

[Swift] 纯文本查看 复制代码
_ = navigationController?.popViewController(animated: true)


像这样通过 _ 来省略掉了。虽然比较难看,考虑到 Swift 是一门严格的语言,就忍忍吧。




3、Protocol 实现一定要在对应的 extension 里

以前写代码时会有不注意的地方,比如 UITableViewDelegate 和 UITableViewDataSource,我分别用 extension 来实现,但是在具体的实现中没注意,把 delegate 的一个方法放进了 dataSource 的 extension 去实现,项目也能完全正常运作。

但是在 Swift 3.0 下,如果你在一个 extension 里实现一个 protocol,那么这个 protocol 的方法一定要在这个 extension 里面能找到,而不能在另外一个 extension 里或者主 class 或 struct 里面。不然会有类似这样的警告:

[Swift] 纯文本查看 复制代码
Objective-C method 'tableView:canEditRowAt:' provided by method 'tableView(_:canEditRowAt:)' does not match the requirement's selector ('tableView:canEditRowAtIndexPath:')


这也是 Swift 3 编译变得更严格的一个表现。




4、Implicitly Unwrapped Optionals 的坑

在 Swift 2 的项目中,我们可能存在这样不是特别安全的代码:

[Swift] 纯文本查看 复制代码
var greetings: String!
greetings = "Hello"
print("\(greetings) 图拉鼎")


这里会输出:

[Swift] 纯文本查看 复制代码
Hello 图拉鼎


没有任何问题。但是在 Swift 3 中,因为 Optional 的安全机制起作用了,会变成:

[Swift] 纯文本查看 复制代码
Optional("Hello") 图拉鼎


这个结果不是我们想要的。从这点也可以看到,Swift 3 的 IUO 行为变得更安全了,默认会把 IUO 变成 Optional。如果想要达到和 Swift 2 一样的效果,就得用:

[Swift] 纯文本查看 复制代码
print("\(greetings!) 图拉鼎")


这时你也注意到了,Swift 始终在用 ! 提醒你用 IUO 不那么安全。

所以趁这个机会可以好好重构一下老代码吧~(知乎暂时不支持 Swift 语言的代码高亮,我已经反馈该问题了)




5、转化器一些奇怪的坑

如果你是用 Xcode 的自动转换器来转 Swift 3 项目的,应该会遇到一些奇怪的坑,特别举例:

  • UIControlState.normal 会转换成 UIControlState(),还好其他状态不会这样,所以全局搜索一次再替换即可;
  • IndexPath 明明是一个去 NS 的 Foundation 类型了,但是自动转换后代码经常会有 (indexPath as NSIndexPath) 这样的东西,完全可以去掉;
  • 所有 NSNotification.Name 都可以重构成 Notification.Name,但是转换器并没有做这件事情。与其同时,自己用字符串定义的 NotificationName,现在可以统一基于 extension 去扩展啦。





6、后记

适配完奇点这个两万多行代码的项目后,实际上可以总结的远远不止上面这些,我只是挑了一些典型来讲。更何况,我只是完成了第一步「适配」而已,更多的工作,比如把 API 命名更加 Swift 3 化,充分利用 Swift 3 的一些特性来重构项目等等都还没有做。

所以在接下去的路上,应该还会去总结和学习一些东西吧。祝大家适配 Swift 3 愉快



推荐再看看全球最大的Swift开发者社区敏捷大拇指Swifthumb.com)上的《Swift 3 迁移工作总结




作者:图拉鼎


都看到这里了,就把这篇资料推荐给您的好朋友吧,让他们也感受一下。

回帖是一种美德,也是对楼主发帖的尊重和支持。

*声明:敏捷大拇指是全球最大的Swift开发者社区、苹果粉丝家园、智能移动门户,所载内容仅限于传递更多最新信息,并不意味赞同其观点或证实其描述;内容仅供参考,并非绝对正确的建议。本站不对上述信息的真实性、合法性、完整性做出保证;转载请注明来源并加上本站链接,敏捷大拇指将保留所有法律权益。如有疑问或建议,邮件至marketing@swifthumb.com

*联系:微信公众平台:“swifthumb” / 腾讯微博:@swifthumb / 新浪微博:@swifthumb / 官方QQ一群:343549891(满) / 官方QQ二群:245285613 ,需要报上用户名才会被同意进群,请先注册敏捷大拇指

嗯,不错!期待更多好内容,支持一把:
支持敏捷大拇指,用支付宝支付10.24元 支持敏捷大拇指,用微信支付10.24元

评分

参与人数 1金钱 +10 贡献 +10 专家分 +10 收起 理由
Anewczs + 10 + 10 + 10 32个赞!专家给力!

查看全部评分

本帖被以下淘专辑推荐:

Ding 发表于 2016-10-31 13:39:06 | 显示全部楼层
整理得不错。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

做任务,领红包。
我要发帖

分享扩散

都看到这里了,就把这资料推荐给您的好朋友吧,让他们也感受一下。
您的每一位朋友访问此永久链接后,您都将获得相应的金钱积分奖励
关闭

站长推荐 上一条 /3 下一条

热门推荐

合作伙伴

Swift小苹果

  • 北京治世天下科技有限公司
  • ©2014-2016 敏捷大拇指
  • 京ICP备14029482号
  • Powered by Discuz! X3.1 Licensed
  • swifthumb Wechat Code
  •   
快速回复 返回顶部 返回列表