OC与Swift混编项目迁移到Swift4.2小记

2,048 阅读3分钟

前言

自从Xcode10正式版发布之后, 先吃螃蟹的朋友赞叹了Dark Mode的惊艳, 同时也报告说, 打包上传到APPStroe后, 监测到线上 iOS9.3设备大面积crash的记录, 最后被证实是Xcode10的问题.

出于此原因考虑, 我便一直在使用Xcode9.4.1Swift4进行混编项目的开发.

然而每每使用低版本的Xcode打包上传APPStore时, 就会收到苹果的官方警告邮件

如邮件内容所示, 到2019年的3月份便不可以再使用低版本Xcode进行打包上传操作了.

于是, 我只好开始了迁移之路.

开始迁移

使用当前 Xcode10.1(10B61)打开之后, 在Build Setting中搜索 Swift Language Version, 将对应的值改为Swift 4.2,然后开始编译, 此时会出现非常多的Error, 多为ABI的变动, 根据提示进行修改即可.

AVAudioSession的更改

然而有一处例外:
当项目中通过Swift使用了 AVAudioSession setCategory这个方法时, 会被告知方法在Swift中不可用.跳转才发现 API已经变化成了

/* set session category and mode with options */
    @available(iOS 10.0, *)
    open func setCategory(_ category: AVAudioSession.Category, mode: AVAudioSession.Mode, options: AVAudioSession.CategoryOptions = []) throws

为了兼容低版本, 思来想去, 比较合适的方案就是使用OC编写一个AVAudioSession的分类用来桥接:

// AVAudioSession+Swift.h:

@import AVFoundation;

NS_ASSUME_NONNULL_BEGIN

@interface AVAudioSession (Swift)

- (BOOL)swift_setCategory:(AVAudioSessionCategory)category error:(NSError **)outError NS_SWIFT_NAME(setCategory(_:));
- (BOOL)swift_setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError NS_SWIFT_NAME(setCategory(_:options:));

@end

NS_ASSUME_NONNULL_END

// AVAudioSession+Swift.m:

#import "AVAudioSession+Swift.h"

@implementation AVAudioSession (Swift)

- (BOOL)swift_setCategory:(AVAudioSessionCategory)category error:(NSError **)outError {
    return [self setCategory:category error:outError];
}
- (BOOL)swift_setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError {
    return [self setCategory:category withOptions:options error:outError];
}

@end

然后在你项目的<#target_name#>-Bridging-Header.himport这个分类:

#import "AVAudioSession+Swift.h"

然后就可以像之前一样调用了.

try AVAudioSession.sharedInstance().setCategory(.playback)

While deserializing SIL vtable for 'Class' in module 'module' error: Abort trap: 6

这类问题分两种, 一种是module是其他的target, 如Pods中的, 另一种是 module是自己的创建的target.

第一种

第一种 只需要将Error所指向的三方库更新到最新版本即可, Xcode10已经发布了快半年了, 这些问题之前也有, 半年的时间, 基本上流行的三方库都已经适配了Swift4.2

第二种

而第二种比较棘手, 一般都是由于 Error中的Class所指向的类, 自己是Swift类, 但是却继承自Objective-C声明编写的类. 我在自己试过一些微调之后发现于事无补, 所以只好将出错的类使用Objective-C重写, 然后在桥接文件中引入, 好在报错的不多, 没用费太多力气.

其他奇怪的错误

迁移完成后 项目跑起来时, 还会出现很多奇怪的问题. 比如调用了某个方法A 会报unrecognize selector *, 以及莫名的函数调用, 如:

(setupNavibar函数中并没用调用任何初始化构造函数)
这类错误, 一般跟以上的俩种问题是一个本质, 需要自己仔细区别, 然后做出相应更新/更改即可.

除开以上的问题, 项目编译时还会在Pods引用的第三方的类中报ABI需要修改的Error, 这时, 只需要找到队形的Target, 在其Build Settings中修改 Swift Language Version为其对应版本即可.

最后, 希望将来适配Swift5时, 不要有这么多坑了...