天天看點

swift調用oc_OC與Swift混編項目遷移到Swift4.2小記OC與Swift混編項目遷移到Swift4.2小記

OC與Swift混編項目遷移到Swift4.2小記

前言

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

出于此原因考慮, 我便一直在使用Xcode9.4.1 及 Swift4進行混編項目的開發.

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

swift調用oc_OC與Swift混編項目遷移到Swift4.2小記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;[email protected] 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:));@endNS_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複制代碼
           

然後在你項目的-Bridging-Header.h中import這個分類:

#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 *, 以及莫名的函數調用, 如:

swift調用oc_OC與Swift混編項目遷移到Swift4.2小記OC與Swift混編項目遷移到Swift4.2小記

(setupNavibar函數中并沒用調用任何初始化構造函數)

這類錯誤, 一般跟以上的倆種問題是一個本質, 需要自己仔細差別, 然後做出相應更新/更改即可.除開以上的問題, 項目編譯時還會在Pods引用的第三方的類中報ABI需要修改的Error, 這時, 隻需要找到隊形的Target, 在其Build Settings中修改 Swift Language Version為其對應版本即可.

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

繼續閱讀