Swift與Objective-C混和編程

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

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


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

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

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

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

普通代碼文件混編方案:

Swift引用OC實現(xiàn)通過橋接頭文件毒返,OC引用Swift實現(xiàn)直接importProductModuleName-Swift.h這個文件即可租幕。

OC引用Swift實現(xiàn)

ProductModuleNameBuild Settings里面配置:

默認用ProductName,可以支持自定義拧簸。(注明:Framework項目不支持自定義)

Swift引用OC實現(xiàn)

Swift引用OC實現(xiàn)稍微麻煩一點劲绪,需要自己生成一個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選項。

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

#import "XYZCustomCell.h"    

#import "XYZCustomView.h"   

#import "XYZCustomViewController.h"

Swift中用如下代碼訪問:

let myOtherCell = XYZCustomCell()    

myOtherCell.subtitle = "Another custom cell"

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

Framework項目中使用代碼混編方案:

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

Swift引用OC實現(xiàn)

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

#import "XYZCustomCell.h"    

#import "XYZCustomView.h"    

#import "XYZCustomViewController.h"

OC引用Swift

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

引用外部Framework時混編

方案:

重要前提

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

external framework混編

在這種情況下當(dāng)前App使用外部Framework是不關(guān)心其內(nèi)部到底是Swift實現(xiàn)夫晌、OC實現(xiàn)還是本身就是混編實現(xiàn)的雕薪。只需要Swift使用Framework邏輯時添加import FrameworkName,OC使用時在任意.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混編時遇到的問題

  1. Evenote-Mac這個奇葩的Framework名字在生成umbrella header的時候報錯:

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

因為名字中有-字符勺拣,所以只能替換或者去掉;

  1. 改名時建議直接改target的名字鱼填,只改module的名字就會報錯:

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

參考鏈接

  1. Mixed language framework

  2. 鏈接1回答中還有個Demo

  3. 官方對Umbrella Framework的一點介紹

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末药有,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子苹丸,更是在濱河造成了極大的恐慌愤惰,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赘理,死亡現(xiàn)場離奇詭異宦言,居然都是意外死亡,警方通過查閱死者的電腦和手機商模,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門奠旺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人施流,你說我怎么就攤上這事响疚。” “怎么了瞪醋?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵忿晕,是天一觀的道長。 經(jīng)常有香客問我银受,道長践盼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任宾巍,我火速辦了婚禮咕幻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘顶霞。我一直安慰自己谅河,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布确丢。 她就那樣靜靜地躺著绷耍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鲜侥。 梳的紋絲不亂的頭發(fā)上褂始,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天,我揣著相機與錄音描函,去河邊找鬼崎苗。 笑死狐粱,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胆数。 我是一名探鬼主播肌蜻,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼必尼!你這毒婦竟也來了蒋搜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤判莉,失蹤者是張志新(化名)和其女友劉穎豆挽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體券盅,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡帮哈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锰镀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娘侍。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖泳炉,靈堂內(nèi)的尸體忽然破棺而出憾筏,到底是詐尸還是另有隱情,我是刑警寧澤胡桃,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布踩叭,位于F島的核電站磕潮,受9級特大地震影響翠胰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜自脯,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一之景、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧膏潮,春花似錦锻狗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至叠纷,卻和暖如春刻帚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背涩嚣。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工崇众, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留掂僵,地道東北人。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓顷歌,卻偏偏與公主長得像锰蓬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子眯漩,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,592評論 2 353

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