Swift 版本升级嘛,你们应该都很熟练了,菜单 -> Edit -> Convert -> To Current Swift Syntax...,而后巴拉巴拉一顿操做。emmmn,抱歉,编译过了也不必定能正常使用。git
此次 Swift 3 到 Swift 4 的更新和以前的大版本更新相比,已经平滑了不少,相较以前的动辄几百上千个 error,如今用 Xcode 进行 Convert 以后基本上只须要进行少许人工修正便可,不过仍然有一些点须要注意,本文将会对一些常见的坑或者注意点以及解决方法进行讨论。github
本文以 EFCountingLabel 的 1.0.3 版本和 Xcode 9.0 为例,主要关于原有的 Swift 3 的 CocoaPods 库到 Swift 4 的升级,仍处于 Swift 2 阶段的同窗可暂时忽略本文。swift
首先用 Xcode 打开工程,看一下当前工程设置的 Swift 版本,若是太低的话可能没法直接 Convert,选中须要转换的 target 搜索 swift_ver
便可,如图所示:bash
这里 EFCountingLabel 的 Swift 版本为 3.2,若是是 2.x 的话须要本身想办法先转换成 Swift 3.x...函数
接下来,就是利用 Xcode 实现代码转换了,菜单 -> Edit -> Convert -> To Current Swift Syntax...,而后选中须要转换的 target,点击 Next
按钮便可:post
而后会出现一个转换模式选项,有 Minimize Inference(recommended)
和 Match Swift 3 Behavior
两个选择,苹果推荐的是第一个选项:测试
苹果官方文档对这两个选项的描述以下,大意是:若是选第一个选项,会仅在必要的时候为方法或属性添加 @objc
标志,不过大部分工做须要用户(也就是你)手动完成,好处是能减小最终生成的二进制文件的大小;若是选择第二个选项,则会按 Swift 3 的方式给全部的地方直接添加 @objc
标志(关于 @objc
标志的介绍你们能够参考 Swift 翻译组的这篇文章),缺点就是不会对生成的二进制文件大小进行优化(也就是跟 Swift 3 同样):优化
这里咱们分几种状况:spa
Minimize Inference(recommended)
,检查而且保存自动转换结果便可,而后能够直接跳到下一小节,请忽略下面这一大段;@objc
标志或者对这一点二进制文件体积的缩减并非十分在乎的话,选 Match Swift 3 Behavior
,检查而且保存自动转换结果便可,而后能够直接跳到下一小节,请忽略下面这一大段;Minimize Inference(recommended)
,保存更改,而后按下面的操做去作:1. 编译工程;
2. 修正那些提示你须要添加 @objc 标志的警告(请务必修正,否则即便编译能过运行时也可能会出问题);
3. 修正 Xcode 提示的不须要添加 @objc 标志的代码,持续构建和测试你的代码,直到没有任何警告出现;
4. 打开工程设置;
5. 选中 target,搜索 `@objc` 找到 `Swift 3 @objc Inference` 选项,设为 `Default`。
复制代码
唔,以上这段大概是原文翻译过来的了,官方文档原文如图所示:翻译
须要注意的是,由于咱们这里针对的并非完整的 iOS 项目,而是 CocoaPods 库,若是你的 OC Demo 没有调用库中须要暴露的功能(或者干脆没有 OC Demo),辣么编译器可能彻底不会给你任何提示而是直接经过编译了,直到你某一天在一个 OC 工程中引入这个库才会发现并不能调用到某些方法或获取某些属性。
因此其实麻烦之处在于,编译器并不会给你任何提示,由于编译器也不知道哪些类 / 属性 / 方法须要暴露,哪些须要被优化掉,须要开发人员本身决定并手动添加对应的 @objc
标志,总结起来的话有如下几点:
#selector
的方式调用的话,能过编译而且在运行时直接找不到对应方法而闪退,建议升完 Swift 4 检查一下全部的 #selector 调用);Perform Changes
按钮便可;Swift 3 @objc Inference
设置(若是有的话)改成 Default
,以前改过的话就不用改了;swift_ver
,能够看到当前的 Swift Language Version
已是 Swift 4
了。剩下少许方法名变更之类的更新你们能够根据提示自行修改,到这里基本就完成了升级过程,不过先别急,接下来咱们看注意事项。
如下状况必需要给对应的属性或方法添加 @objc
标志(固然,他们所在的类确定也须要添加 @objc
标志),不论是经过 OC 仍是 Swift 调用:
@selector()
或 #selector()
方式调用的函数;这些有部分在官方文档中也有说起:
Swift 的版本控制粒度在 framework 层面,也就是说同一个工程中不一样的 framework 能够是按不一样版本的 Swift 进行编译的,因此并不须要等待项目依赖的全部 Pods 库都支持 Swift 4 后再更新,彻底能够将已经升级 Swift 4 的库先用起来。
Swift 3 @objc Inference
选项是干啥的?在 Swift 4 以前,编译器对 Objective-C 自动提供了一些 Swift 声明。例如,编译器会为 NSObject 子类的全部方法建立 Objective-C 入口点,该机制称为 @objc 推断(@objc Inference)。
在 Swift 4 中,这种自动的 @objc 推断已被废弃,由于生成全部这些 Objective-C 入口点有代价,会增大最终的二进制文件体积。当 Swift 3 @objc Inference
设置为 On
时,它会按照 Swift 4 以前的模式运行,不进行优化,也就是隐式为咱们编写的全部 Swift 代码提供 OC 入口。
可是,当设置为 On
时 Xcode 会报一个警告,建议修复这个警告,并将设置切换到 Default
。新的 Swift 项目的默认为“Default”。能够理解为该项设置为 On
时和上文代码转换时选择 Match Swift 3 Behavior
选项效果相似。
升级完请务必跑一遍总体测试流程,暗坑无数,以防万一,祝你们线上稳定。
若有任何知识产权、版权问题或理论错误,还请指正。 https://juejin.im/post/5a32180551882554b83790ca 转载请注明原做者及以上信息。