Swift與Objective-C混和編程

14年6月3日蘋果發(fā)布Swift以來,這門語言以讓人驚訝的速度在成長,越來越多的開發(fā)者關(guān)注學(xué)習(xí),很多App和開源庫也在從Objective-C遷移到Swift上。

Swift語法確實(shí)更新進(jìn)、更漂亮,而在實(shí)際開發(fā)過程中,由于Objective-C更貼近底層,可以使用如OC Runtime這樣的黑魔法,很多開源庫也是依賴其實(shí)現(xiàn)。因此OC和Swift混編應(yīng)該一個(gè)長期的趨勢,之前只是依賴于Xcode自動(dòng)引入bridge header等類似的機(jī)制,沒有仔細(xì)去理解,借著新做項(xiàng)目用到evernote oc庫的機(jī)會(huì)好好的總結(jié)一下。蘋果提供的Swift與Objective-C混編方案都是基于Xcode和LLVM編譯,采用Mix and Match機(jī)制。


從開發(fā)者實(shí)現(xiàn)角度根據(jù)不同的混編場景可以分為如下幾種情況:

  • 普通代碼混編:項(xiàng)目內(nèi)普通代碼文件混編(.swift內(nèi)使用OC的.h和.m文件或者反過來,包括.a形式項(xiàng)目的開發(fā)),采用的bridge方案;

  • 開發(fā)Framework混編:如果你的項(xiàng)目是輸出一個(gè)Framework,混編方式稍有不同,姑且成為umbrella方案;

  • 引用外部Framework和宿主App混編:如果你的項(xiàng)目引用一個(gè)外部提供的Framework(無論這個(gè)Framework是單一語言開發(fā)還是本身就是混編的),混編方案也有不同。> 詳細(xì)的原理參見上文提到的官方文檔,本文主要關(guān)注三種方式的實(shí)現(xiàn)以及可能遇到的問題。

普通代碼文件混編方案:

Swift引用OC實(shí)現(xiàn)通過橋接頭文件,OC引用Swift實(shí)現(xiàn)直接importProductModuleName-Swift.h這個(gè)文件即可。

OC引用Swift實(shí)現(xiàn)

ProductModuleNameBuild Settings里面配置:

默認(rèn)用ProductName,可以支持自定義。(注明:Framework項(xiàng)目不支持自定義)

Swift引用OC實(shí)現(xiàn)

Swift引用OC實(shí)現(xiàn)稍微麻煩一點(diǎn),需要自己生成一個(gè)bridge header文件,和創(chuàng)建普通.h方式相同File > New > File > (iOS, watchOS, tvOS, or OS X) > Source > Header File,名字隨意,然后配置到Build Settings - Swift Compiler - Code Generation下的Objective-C Bridging Header選項(xiàng)。

注意路徑從項(xiàng)目根目錄開始計(jì)算,可以使用..來指定與根目錄平級目錄。bridge header內(nèi)import所有想要在swift中使用的OC類,就會(huì)作為一個(gè)module在swift中使用。例如:

#import "XYZCustomCell.h"    

#import "XYZCustomView.h"   

#import "XYZCustomViewController.h"

Swift中用如下代碼訪問:

let myOtherCell = XYZCustomCell()    

myOtherCell.subtitle = "Another custom cell"

FYI. 語言類型為Swift的項(xiàng)目引入OC文件時(shí)Xcode會(huì)給個(gè)創(chuàng)建bridge header的提示,自己會(huì)配置了之后用處不大:

Framework項(xiàng)目中使用代碼混編方案:

Umbrella Header的相關(guān)知識蘋果沒有給出很明確的說明,只有以前介紹Umbrella Framework的時(shí)候介紹過,找了很久發(fā)現(xiàn)iOS - Umbrella Header在framework中的應(yīng)用這篇文章介紹的很好,詳細(xì)的內(nèi)容可以進(jìn)入了解。

Swift引用OC實(shí)現(xiàn)

現(xiàn)在我們只需要了解Framework里面Swift引用OC邏輯需要一個(gè)與ProductName同名的.h文件作為Umbrella Header,如果不存在則創(chuàng)建一個(gè)。不需要在Build Settings配置因?yàn)檫@文件是map modules的時(shí)候自動(dòng)指定的,如果基于某種原因(比如這個(gè)同名文件已經(jīng)被用來寫其他邏輯)一定要自定義的話可以參考上面文章里介紹的方法。第二步到Build Settings - Packaging中將Defines Module選項(xiàng)設(shè)為YES。然后將Swift中需要引用的OC邏輯引用進(jìn)來,訪問方式同普通代碼混編

#import "XYZCustomCell.h"    

#import "XYZCustomView.h"    

#import "XYZCustomViewController.h"

OC引用Swift

實(shí)現(xiàn)OC引用Swift同樣需要將Defines Module選項(xiàng)設(shè)為YES,其余和普通代碼混編相比只是改了個(gè)引用文件的方式:#import

引用外部Framework時(shí)混編

方案:

重要前提

這里有一個(gè)重要的前提是這個(gè)外部Framework在編譯時(shí)必須開啟了Defines Module,如果沒有開啟并且沒有Framework源碼的情況下還是繞路吧。

external framework混編

在這種情況下當(dāng)前App使用外部Framework是不關(guān)心其內(nèi)部到底是Swift實(shí)現(xiàn)、OC實(shí)現(xiàn)還是本身就是混編實(shí)現(xiàn)的。只需要Swift使用Framework邏輯時(shí)添加import FrameworkName,OC使用時(shí)在任意.m文件中添加@import FrameworkName;語法即可。

混編后哪些邏輯可以被另一種語言引用到?

Swift中可以被OC引用的邏輯:

  • public關(guān)鍵字;

  • 有bridging header的target中用internal關(guān)鍵字修飾;

  • private修飾的關(guān)鍵字通常是訪問不到的,除了@IBAction, @IBOutlet, 和 @objc標(biāo)記;

OC中由于開發(fā)習(xí)慣的原因基本上頭文件中的屬性、方法都可以被swift訪問到。

Evenote-Mac Framework混編時(shí)遇到的問題

  1. Evenote-Mac這個(gè)奇葩的Framework名字在生成umbrella header的時(shí)候報(bào)錯(cuò):

warning: EvernoteSDK-Mac is not a valid PRODUCT_NAME for use with framework targets enabling DEFINES_MODULE (name is not a valid C99 extended identifier)

warning: no umbrella header found for target 'EvernoteSDK-Mac', module map will not be generated

因?yàn)槊种杏?code>-字符,所以只能替換或者去掉;

  1. 改名時(shí)建議直接改target的名字,只改module的名字就會(huì)報(bào)錯(cuò):

Warning: PRODUCT_MODULE_NAME may not be overridden for framework target 'EvernoteSDKMac'

參考鏈接

  1. Mixed language framework

  2. 鏈接1回答中還有個(gè)Demo

  3. 官方對Umbrella Framework的一點(diǎn)介紹

  4. 對Umbrella Framework的一篇更好的介紹

  5. so上有關(guān)framework name的回答

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,516評論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內(nèi)容