下面来看UICollectionViewDataSource上的此方法:
func collectionView( _ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView假设您的类实现UICollectionViewDataSource并声明以下方法:
func collectionView( collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: IndexPath) -> UICollectionReusableView您能发现其中的差异吗?这并不轻松,但差异却的确存在。 这时您的类将只进行编译而不会对定义的签名进行更新,因为其属于一项可选协议方法。
幸运的是,编译器会给出警告信息以帮助大家发现此类问题——但并非全部问题。因此我们必须认真审查一切包含可选方法的类型实现协议——例如大部分UIKist委托以及数据源协议——并验证其正确性。搜索“func collectionView(collectionView:”等文本(请注意第一项参数标签,其明显属于Swift 2产物)能帮助大家在自己的代码库中发现此类问题。
涉及默认方法实现的协议
某些协议可能会通过协议扩展采用默认方法实现。如果某项协议的方法签名在Swift 2到Swift 3的迁移过程中发生了变更,则必须确保这一变更体现在全部相关位置。编译器本身不会理会协议扩展是否实现或者您的类型实现是否正确,但若二者出现问题则编译过程显然无法成功。
包含字符串原始值的枚举类型
在Swift 3中,枚举类型由lowerCamelCase的命名惯例进行指定。Xcode代码转换工具会自动对现有枚举进行适当变更。然而如果其中的原始值类型为String,则其会自动跳过对应枚举。这样的处理方式可以理解,因为开发者有可能会利用某个与枚举类型名称相匹配的String对其中一条枚举进行初始化。如果大家变更该枚举类型名称,则可能破坏其余位置的初始化过程。您可能认为能够通过手动小写某些枚举类型的方式“完成任务”,但这种作法只适用于不会破坏其它基于客串的初始化过程的前提之下。
第三方库API变更
与大多数应用类似,我们的应用也存在一定的第三方库依赖性。在迁移当中,我们需要更新这些利用Swift编写的库。这项工作看似简单,但却仍然需要高度关注:包括仔细阅读发行说明,特别是您所依赖的库已经经历了大版本升级(特别是其对应的语言进行了大版本升级)。通过这种方式,我们得以发现了不少易被编译器所忽略的API变更。
下一步工作
现在我们的master分支已经彻底转换为Swift 3,而且不再有任何利用Swift 2进行的开发工作。那么,这是否意味着迁移工作已经全面结束?
还不一定。正如之前所提到,在代码转换过程中,我们仅仅对Swift 2代码进行了直观的Swift 3转换,这意味着我们还未能充分发挥Swift 3在安全性及其它便利层面的增强优势。
作为一项需要持续推进的工作,我们将始终关注各类潜在的改进空间。
更高水平的细粒度控制
在默认情况下,Xcode代码转换工具会将访问控制修饰符private转换为fileprivate,而public则被转换为open。这代表着代码进行实现“字面”形式转换,保证代码的工作效果与原本相统一。
然而,这同时意味着开发者亦错过了考量新的private与public是否真的最适合用于实现预期效果的机会。下一步,我们将审查访问控制机制的字面转换结果,并思考如何利用Swift 3更为强大的表达能力提供更高水平的细粒度控制方案。
Swift 3方法命名
在对代码进行手动转换时(即当Xcode转换工具无法实现或者进行基础重建时),我们通常采取“字段”方式变更方法名称,确保调用机制能够继续正常起效。以下列Swift 2.3方法签名为例:
func incrementCounter(counter: Counter, atIndex index: Int)为了更快更简便地完成面向Swift 3的代码编译转换,我们将其变更为:
func incrementCounter(_ counter: Counter, atIndex index: Int)不过更具Swift 3风格的调整方式显然应该是:
func increment(_ counter: Counter, at index: Int)接下来的工作是找到那些进行快速命名的实例,有针对性地更新方法签名以遵循Swift 3的命名约定。
更安全地运用隐式解析可选项