迁移到 Swift 4.2

Xcode 10.0 带有一个 Swift 迁移工具,用来帮助你将工程迁移到 Swift 4.2。

之前版本的迁移指南,查看 迁移到 Swift 4

迁移前准备

确保你想要迁移的工程能在 Swift 3 或者 Swift 4 模式下成功构建,并且能够通过所有的测试。你可能需要首先解决由于编译器改变引起的错误。

强烈建议在 source control 下管理项目。这将使你很容易查看通过迁移助理应用在项目中的改变,并且能在需要的时候丢弃这些改变并重新进行迁移。

当对你的项目有意义时你决定何时并且是否按目标迁移。虽然绝对鼓励迁移到 Swift 4.2,但是这不是一个要么全有要么全无的过程,Swift 3, 4,和 4.2 targets 可以共存并互相链接。

迁移助理进行 迁移器构建 以使用你选择的 scheme 收集改变,因此将要处理的目标是包含在 scheme 中的目标。为了查看和修改 scheme 中的内容,调用 Edit Scheme... 表并从左侧的列中选择 Build 选项卡, 并且确保你所有的 targets 和单元测试都被包含在内。

如果你的项目基于其他被 Carthage 和 CocoaPods 提供的开源项目 ,详询 使用 Carthage/CocoaPods 的工程 章节。

Swift 迁移助手

当第一次使用 Xcode 10 打开你的工程时,将会在问题导航器中看到一个迁移机会项:点击它将启动一个询问你是否要进行迁移的菜单。你可以选择稍后提示或手动在菜单栏中的 Edit -> Convert -> To Current Swift Syntax... 下重新唤起该迁移助手。

你将看到要进行迁移的目标列表。没有包含任何 Swift 代码的目标将不会被选中。

如果你选中的所有目标都是 Swift 4 模式,那么将只有一个迁移工作流,若为 Swift 3 目标,则有两种 @objc Inference 模式进行选择:

  • 最小化迁移: 在代码中需要给基于静态推断的地方添加一个 @objc 修饰符。使用这种选项后,你需要遵循并完成 Swift 4 最小化推断迁移来进行代码转换的详细手动操作步骤。

  • 匹配 Swift 3 行为: 添加 @objc 修饰符在代码中任何通过编译器做了隐式推断的地方。这个选项不会改变你的二进制文件大小,它只是显式的添加了 @objc 修饰符在 Swift 3 中做了隐式推断的任何地方。

关于这两个选项的更多信息和含义,请看这篇 Xcode 帮助文章 Migrate to Swift 4 @objc inference.

点击 下一步 打开预览生成表,并且迁移助手将启动迁移构建来获取改变的源码。当它完成后,你将在点击时看到所有生效的更改。它还会改变迁移目标的 Swift 语言版本的构建设置为 Swift 4.2 。

在处理目标时可能会出现很多问题,这些问题可能会对迁移过程产生负面影响。切换到报表导航器并选择添加的条目;这是转换构建日志。检查日志可能出现的错误。

如果你看到的错误是关于目标代码签名,尝试在构建设置中关闭代码签名。如果你看到了其它错误,可看 file a bug report ,其还包括了一些报错细节。若还有错,可能的话,我们强烈推荐您附加上一个工程来说明迁移错误来进行反馈。

Swift 4.2 迁移更改概述

迁移器建议的绝大多数更改数据是通过对比先前 SDK 和当前 SDK 产生的,举个例子,它可能会导致重命名标识符和类型,且正常情况下编译器可以修复它。

最流行的 SDK 更改是将全局常量改为静态类型属性和改变字符串常量为 Swift 的枚举。这些事情可以被迁移器自动完成。

如果你是迁移来自 Swift 3 的代码,还可以参考去年的这篇文章  Migrating to Swift 4

迁移之后

虽然迁移器将会给你完成一些机械化的更改,但可能需要你进行更多的手动修改才能在迁移器应用改变后完成工程构建。

你可能会看到编译器的关联修改错误,虽然迁移器被设计为是合并 Swift 4 编译器提供的修复代码,但如果这些修复不在 100% 的时间中可用则不会生效。

甚至如果它编译通过,这些由迁移器提供的修复代码不一定是最佳的。请用你极佳的判断力去检查,更改它们直到适合你的工程。

可以查看 Known Migration Issues 部分的内容,提供了当尝试迁移你的工程时会遇到的问题。


已知的迁移问题

SDK

  • 你可能会看到这样的错误 Cannot assign value of type 'Int' to type 'UIBackgroundTaskIdentifier'
    • 解决办法:移除迁移器插入的转换方法 / 在合适的地方添加上 .rawValue
  • 你可能会看到这样的错误 binary operator '|=' cannot be applied to two 'UIAccessibility.Traits' operands
    • 解决办法: | 运算符计算完左值和右值的结果直接分配 UIAccessibilityTraits(rawValue:) 并且赋给左值
  • UIApplicationMain 已显式的修改其第二个参数的类型去匹配 CommandLine.unsafeArgv 类型
    • 解决办法:替换第二个参数为 CommandLine.unsafeArgv 类型。
  • 对于使用 AppKit 的 macOS 应用来说,你可能会看到这样的错误 argument labels '(rawValue:)' do not match any available overloads
    • 解决办法:移除参数的 rawValue 标签。

其它

  • Swift 的迁移构建忽略了 Other Swift Flags 构建设置
    • 因为缺少没有 #else 的条件编译分支并且未传递预期 -D 标志,所以表现出了缺失错误返回。
    • 解决办法:在迁移之前尝试添加 #else 子句与合适的断言 / fatalError()
  • 通过 Swift 迁移助手应用的更改没有出现在打开的文档中
    • 解决办法:返回选择一个不同的文件,改变它将要现实的内容。
  • 对于 main.swift 文件,迁移器可能会在文件底部添加协助方法,但它们将不会被高阶表达式所信任。
    • 解决办法:移动该协助方法到文件 import 之后开始的地方


使用 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 ,然后运行 Edit -> Convert -> To Current Swift Syntax 去迁移剩下的 scheme 。或者你可以创建一个包括了来自你工程所有目标的 scheme ,并且在运行迁移助手前选中它。

本文章首发在 LearnKu.com 网站上。
上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~