OC與Swift混編專案遷移到Swift4.2小記

OneKyle發表於2019-02-28

前言

自從Xcode10正式版釋出之後, 先吃螃蟹的朋友讚歎了Dark Mode的驚豔, 同時也報告說, 打包上傳到APPStroe後, 監測到線上 iOS9.3裝置大面積crash的記錄, 最後被證實是Xcode10的問題.

出於此原因考慮, 我便一直在使用Xcode9.4.1Swift4進行混編專案的開發.

然而每每使用低版本的Xcode打包上傳APPStore時, 就會收到蘋果的官方警告郵件

OC與Swift混編專案遷移到Swift4.2小記

如郵件內容所示, 到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 *, 以及莫名的函式呼叫, 如:

OC與Swift混編專案遷移到Swift4.2小記
(setupNavibar函式中並沒用呼叫任何初始化建構函式)
這類錯誤, 一般跟以上的倆種問題是一個本質, 需要自己仔細區別, 然後做出相應更新/更改即可.

除開以上的問題, 專案編譯時還會在Pods引用的第三方的類中報ABI需要修改的Error, 這時, 只需要找到隊形的Target, 在其Build Settings中修改 Swift Language Version為其對應版本即可.

最後, 希望將來適配Swift5時, 不要有這麼多坑了...

相關文章