迁移到 Swift 4.2
Xcode 10.0 配备了 Swift 迁移工具,可帮助您将项目迁移到 Swift 4.2。
有关先前版本的迁移指南,请参阅 迁移到 Swift 4。
迁移前准备
确保您要迁移的项目在 Swift 3 或 Swift 4 模式下成功构建,并且所有测试都通过。您可能需要首先解决由于编译器更改而导致的错误。
强烈建议在源代码控制下管理您的项目。这将使您能够轻松查看通过迁移助手应用的更改,并在需要时放弃它们并重新尝试迁移。
您可以决定何时以及是否在每个目标的基础上进行迁移,这对于您的项目来说是有意义的。虽然绝对鼓励迁移到 Swift 4.2,但这并非一个全有或全无的过程,因为 Swift 3、4 和 4.2 目标可以共存并链接在一起。
迁移助手会执行迁移器构建以收集更改,使用您选择的 scheme,因此将要处理的目标是 scheme 中包含的目标。要查看和修改 scheme 中包含的内容,请调用编辑 Scheme…表单,并从左侧的列中选择Build选项卡,并确保包含所有目标及其单元测试。
如果您的项目依赖于 Carthage 或 CocoaPods 提供的其他开源项目,请查阅 使用 Carthage/CocoaPods 项目 部分。
Swift 迁移助手
当您首次使用 Xcode 10 打开您的项目时,您将在 Issue Navigator 中看到一个迁移机会项目:单击它以激活一个工作表,询问您是否要迁移。您可以稍后提醒自己,或从菜单Edit -> Convert -> To Current Swift Syntax…手动调用迁移器。
您将看到要迁移的目标列表。不包含任何 Swift 代码的目标将不会被选中。
如果所有选定的目标都处于 Swift 4 模式,则只有一个迁移工作流程,但对于 Swift 3 目标,@objc
推断有两种选择
- 最小化推断:仅在基于静态推断需要时,才将 @objc 属性添加到您的代码中。使用此选项后,您需要按照完成 Swift 4 最小化推断迁移中的手动步骤来完成转换。
- 匹配 Swift 3 行为:在编译器隐式推断的任何位置,将 @objc 属性添加到您的代码中。此选项不会更改您二进制文件的大小,因为它在 Swift 3 隐式添加 @objc 属性的任何位置都显式添加了它们。
有关这两种选择的更多信息和含义,请参阅 Xcode 帮助文章 迁移到 Swift 4
@objc
推断。
单击Next将弹出Generate Preview表单,助手将启动迁移构建以获取源代码更改。完成后,您将看到一旦单击“Save”后将应用的所有更改。 这还将把迁移目标的Swift Language Version构建设置更改为Swift 4.2。
处理目标时可能存在问题,这将对迁移过程产生负面影响。切换到Report Navigator并选择添加的Convert条目;这是转换构建日志。检查日志中可能出现的错误。
如果您看到关于无法对目标进行代码签名的错误,请尝试从目标的构建设置中禁用代码签名。如果您看到其他错误,请提交错误报告并包含详细信息。强烈建议您附加一个项目,以说明可能的错误迁移。
Swift 4.2 迁移更改概览
迁移器建议的大部分更改来自对先前 SDK 和当前 SDK 的比较生成的数据,这可能会导致标识符和类型重命名,例如;以及来自正常的编译器修复。
最普遍的 SDK 更改是将全局常量移动到静态类型属性中,并将字符串常量转换为 Swift 枚举 case。这些都由迁移器自动处理。
如果您从 Swift 3 代码迁移,另请参阅去年迁移器从 迁移到 Swift 4 的迁移更改概览。
迁移后
虽然迁移器将为您处理许多机械更改,但在应用迁移器更改后,您可能仍需要进行更多手动更改才能构建项目。
您可能会看到与修复相关的编译器错误;虽然迁移器旨在合并 Swift 4 编译器提供的修复,但如果某些修复不是 100% 适用,则可能不会应用它们。
即使编译正常,迁移器提供的代码也可能不是理想的。请使用您的最佳判断,并检查更改是否适合您的项目。
请参阅已知迁移问题部分,了解您在尝试迁移项目时可能遇到的一系列问题。
已知迁移问题
SDK
- 您可能会看到类似
Cannot assign value of type 'Int' to type 'UIBackgroundTaskIdentifier'
的错误- 解决方法:删除迁移器插入的转换函数 / 根据需要添加 .rawValue
- 您可能会看到类似
binary operator '|=' cannot be applied to two 'UIAccessibility.Traits' operands
的错误- 解决方法:
|
LHS 和 RHS 的原始值,将结果传递给UIAccessibilityTraits(rawValue:)
并分配给 LHS
- 解决方法:
- UIApplicationMain 已更改其第二个参数的类型,以完全匹配
CommandLine.unsafeArgv
的类型- 解决方法:将第二个参数替换为
CommandLine.unsafeArgv
。
- 解决方法:将第二个参数替换为
- 对于使用
AppKit
的 macOS 应用程序,您可能会看到类似argument labels '(rawValue:)' do not match any available overloads
的错误- 解决方法:删除
rawValue:
参数标签。
- 解决方法:删除
其他
- Swift 迁移构建正在忽略
Other Swift Flags
构建设置- 表现为缺少返回错误,这是由于条件编译分支没有
#else
并且没有传递任何预期的 -D 标志。 - 解决方法:尝试在迁移之前添加带有适当断言 /
fatalError()
的#else
子句(如果需要)
- 表现为缺少返回错误,这是由于条件编译分支没有
- 通过 Swift 迁移助手应用的更改未在打开的文档中显示
- 解决方法:切换到其他文件再切换回来,更改将显示出来。
- 对于
main.swift
文件,迁移器可能会在文件底部添加辅助函数,并且它们在前面的顶层表达式中不可用。- 解决方法:将辅助函数移动到导入语句后的文件开头。
使用 Carthage/CocoaPods 项目
以下是使用 Carthage、CocoaPods 或 Swift Package Manager 等包管理器迁移具有外部依赖项的项目时需要考虑的一些要点。
- 建议使用源代码依赖项而不是二进制 Swift 模块,因为 Swift 3.1 模块将与 Swift 3.2/4 模块不兼容,除非您可以获得在 Swift 3.2 或 Swift 4 模式下构建的发行版。
- 确保您的源代码依赖项以及您自己的目标在 Swift 3.2 模式下成功构建。
- 如果您已设置框架搜索路径以查找 Carthage 构建文件夹内的二进制 Swift 模块,请删除搜索路径或清除构建文件夹,以确保您仅使用从 Xcode 工作区构建的 Swift 模块。
- 只要您的源代码依赖项可以在 Swift 3.2 模式下构建,就无需迁移它们。
其他
- 如果您的项目中包含涵盖不同目标的多个 scheme,您只会收到需要迁移其中一个 scheme 的通知。您需要手动选择新的 scheme,然后运行Edit -> Convert -> To Current Swift Syntax以迁移其余的 scheme。或者,您可以创建一个包含项目中所有目标的 scheme,并在运行迁移助手之前选择它。