专注、坚持

Swift/Obj-C 混编项目升级 Swift 5.0 踩坑

2019.05.08 by kingcos
Date Note
2019-05-08 Swift 4.2 -> 5.0
2019-07-08 完善内容

Preface

在 ABI 稳定前,每次 Swift 升级都是一个比较「痛苦」的体验。这次笔者花费约总共一天时间将 Swift/Obj-C 混编项目升级到 Swift 5.0,其中还是有一些踩坑经验值得分享的。

Xcode

为了适配 Swift 5.0,首先需要安装 Xcode 10.2。而我们不能完全抛弃 Xcode 10.1,毕竟在未完全转换到 Swift 5.0 的过渡阶段仍然需要使用。因此我们可以将本地的 Xcode 更名为 Xcode-10.1,再在 https://developer.apple.com/download/more/ 检索 Xcode 下载 10.2 版本即可。

⚠️ 注意:为了防止类似 XcodeGhost 事件再次发生,建议从该官方渠道或 App Store 直接下载。

为了便于区分,我们将新的 Xcode 命名为 Xcode-10.2,并打开、同意安装 Xcode Command Line Tools。由于我们目前安装了两个 Xcode,如果需要命令行执行 swiftxcodebuild 等命令,可以使用 xcode-select 来进行切换不同版本。

1

主工程

安装好 Xcode,为了使得我们的项目使用 Swift 5.0,需要将主工程的 PROJECT & TARGETS - Build Settings 中 Swift 版本改为 5.0,这样之后项目中的 Swift 代码即可使用 Swift 5.0 的编译器进行编译等操作。

CocoaPods

我们目前使用的是 CocoaPods 来管理第三方依赖以及组件化的各个库的。因此对于我们自己的 Swift Pod 库,需要将 s.swift_version 更新到 5.0pod install

Rx- 相关

在目前的时间节点上,其实大部分热门的 Swift 库都已经适配了 Swift 5.0 和 Xcode 10.2。我们基本上只需要将 Podfile 中的相应版本更新为相应的版本即可。例如 Rx- 家族最底层的 RxSwift 和 RxCocoa 我们直接使用 5.0.0 版本即可。

2

社区维护 RxOptional 的 4.0.0 版本不再支持 iOS 9 以下的操作系统(参照 RxOptional.podspec),而我们不能因为升级 Swift 5.0 而抛弃 iOS 8 用户。因此我们可以将其 3.6.2 版本引入到私有库中,将 Podspec 中 Swift 版本更新为 5.0,将其语法升级为支持 Swift 5.0,最终在 Podfile 中通过指定 git 仓库地址和 commit 号来使用此库。不过最后发现我们的代码里并没有使用过多该库的地方,因此删掉了对于该库的引用。

另外一个社区维护的 NSObject+Rx 库。在其 master 分支已经支持了 Swift 5.0,但库的贡献者们似乎忘记了打 Tag 并发布到 CocoaPods 了。我已经在 Issue 找到并回复了有相同问题的开发者,有对该库严重依赖的同学可以等待一下。不过与上个库同理,我们对这个库的使用范围太小,所以进行了移除。

try?

相较于前几年的 Swift 更新,Swift 4.2 -> Swift 5.0 中大部分语法的变更都可以使用 Xcode 自带升级助手来帮助升级。但这次有一个比较诡异的错误是「‘self’ used before ‘self.init’ call」,其发生在如下的便利构造函数中:

class Person {
    var name: String

    private init(param: String) throws {
        self.name = param
    }

    convenience init?(arg: String) {
        try? self.init(param: arg)
    }
}
convenience init?(arg1: String) {
    do {
        try self.init(param: arg1)
    } catch {
        return nil
    }
}

Reference