同時使用Swift和Objective-C,怎么做痰娱?

Swift 與 Objective-C 的兼容能力使你可以在同一個工程中同時使用兩種語言弃榨。你可以用這種叫做 mix and match 的特性來開發(fā)基于混合語言的應(yīng)用,可以用 Swfit 的最新特性實(shí)現(xiàn)應(yīng)用的一部分功能梨睁,并無縫地并入已有的 Objective-C 的代碼中鲸睛。


Mix and Match 概述

Objective-C 和 Swift 文件可以在一個工程中并存,不管這個工程原本是基于 Objective-C 還是 Swift坡贺。你可以直接往現(xiàn)有工程中簡單地添加另一種語言的源文件官辈。這種自然的工作流使得創(chuàng)建混合語言的應(yīng)用或框架 target,與用單獨(dú)一種語言時一樣簡單遍坟。

混合語言的工作流程只有一點(diǎn)點(diǎn)區(qū)別拳亿,這取決于你是在寫應(yīng)用還是寫框架。下面描述了普通的用兩種語言在一個 target 中導(dǎo)入模型的情況愿伴,后續(xù)章節(jié)會有更多細(xì)節(jié)肺魁。

在同個應(yīng)用的 target 中導(dǎo)入

如果你在寫混合語言的應(yīng)用,可能需要用 Swift 代碼訪問 Objective-C 代碼隔节,或者反之鹅经。下面的流程描述了在非框架 target 中的應(yīng)用寂呛。

將 Objective-C 導(dǎo)入 Swift

在一個應(yīng)用的 target 中導(dǎo)入一些 Objective-C 文件供 Swift 代碼使用時,你需要依賴與 Objective-C 的橋接頭文件(bridging header)來暴露給 Swift瘾晃。當(dāng)你添加 Swift 文件到現(xiàn)有的 Objective-C 應(yīng)用(或反之)時贷痪,Xcode 會自動創(chuàng)建這些頭文件。

如果你同意酗捌,Xcode 會在源文件創(chuàng)建的同時生成頭文件呢诬,并用 product 的模塊名加上 -Bridging-Header.h 命名。關(guān)于 product 的模塊名胖缤,詳見 Naming Your Product Module

你應(yīng)該編輯這個頭文件來對 Swift 暴露出 Objective-C 代碼阀圾。

作為一個開發(fā)者哪廓,有一個學(xué)習(xí)的氛圍跟一個交流圈子特別重要,這是一個我的iOS開發(fā)交流群:130 595 548初烘,不管你是小白還是大牛都?xì)g迎入駐 涡真,讓我們一起進(jìn)步,共同發(fā)展I隹稹(群內(nèi)會免費(fèi)提供一些群主收藏的免費(fèi)學(xué)習(xí)書籍資料以及整理好的幾百道面試題和答案文檔6吡稀)

在同一 target 中將 Objective-C 代碼導(dǎo)入到 Swift 中

  1. 在 Objective-C 橋接頭文件中,import 任何你想暴露給 Swift 的頭文件吗铐,例如:
1.  // OBJECTIVE-C

3.  #import "XYZCustomCell.h"
4.  #import "XYZCustomView.h"
5.  #import "XYZCustomViewController.h"

  1. 確保在 Build Settings 中 Objective-C 橋接頭文件的 build setting 是基于 Swfit 編譯器东亦,即 Code Generation 含有頭文件的路徑。這個路徑必須是頭文件自身的路徑唬渗,而不是它所在的目錄典阵。

這個路徑應(yīng)該是你工程的相對路徑,類似 Info.plist 在 Build Settings 中指定的路徑镊逝。在大多數(shù)情況下壮啊,你不需要修改這個設(shè)置。

在這個橋接頭文件中列出的所有 public 的 Objective-C 頭文件都會對 Swift 可見撑蒜。之后當(dāng)前 target 的所有 Swift 文件都可以使用這些頭文件中的方法歹啼,不需要任何 import 語句。用 Swift 語法使用這些 Objective-C 代碼座菠,就像使用系統(tǒng)自帶的 Swift 類一樣狸眼。

1.  // SWIFT

3.  let myCell = XYZCustomCell()
4.  myCell.subtitle = "A custom cell"

將 Swift 導(dǎo)入 Objective-C

向 Objective-C 中導(dǎo)入Swift 代碼時,你依賴 Xcode 生成的頭文件來向 Objective-C 暴露 Swift 代碼辈灼。這是自動生成 Objective-C 頭文件份企,它包含了你的 target 中所有 Swift 代碼中定義的接口⊙灿ǎ可以把這個 Objective-C 頭文件看作 Swift 代碼的 umbrella header司志。它以 product 模塊名加 -Swift.h 來命名甜紫。關(guān)于 product 的模塊名,詳見Naming Your Product Module骂远。

你不需要做任何事情來生成這個頭文件囚霸,只需要將它導(dǎo)入到你的 Objective-C 代碼來使用它。注意這個頭文件中的 Swift 接口包含了它所使用到的所有 Objective-C 類型激才。如果你在 Swift 代碼中使用你自己的 Objective-C 類型拓型,確保先將對應(yīng)的 Objective-C 頭文件導(dǎo)入到你的 Swift 代碼中,然后才將 Swift 自動生成的頭文件導(dǎo)入到 Objective-C .m 源文件中來訪問 Swift 代碼瘸恼。

在同一 target 中將 Swift 代碼導(dǎo)入到 Objective-C 中

在相同 target 的 Objective-C .m 源文件中劣挫,用下面的語法來導(dǎo)入Swift 代碼:

1.  // OBJECTIVE-C
2.  #import "ProductModuleName-Swift.h" 

target 中任何 Swift 文件將會對 Objective-C .m 源文件可見,包括這個 import 語句东帅。關(guān)于在 Objective-C 代碼中使用 Swift 代碼压固,詳見 Using Swift from Objective-C

導(dǎo)入到 Swift 導(dǎo)入到 Swift
Swift 代碼 不需要import語句 #import
Objective-C 代碼 不需要import語句靠闭;需要 Objective-C `umbrella頭文件 #import "Header.h"

在同個 Framework 的 target 中導(dǎo)入

如果你在寫一個混合語言的框架帐我,可能會從 Swift 代碼訪問 Objective-C 代碼,或者反之愧膀。

將 Objective-C 導(dǎo)入 Swift

要將一些 Objective-C 文件導(dǎo)入到同個框架 target 的 Swift 代碼中去拦键,你需要將這些文件導(dǎo)入到 Objective-C 的 umbrella header來供框架使用。

在同一 framework 中將 Objective-C 代碼導(dǎo)入到 Swift 中

確保將框架 target 的 Build Settings > Packaging > Defines Module 設(shè)置為 Yes檩淋。然后在你的 umbrella header 頭文件中導(dǎo)入你想暴露給 Swift 訪問的 Objective-C 頭文件芬为,例如:

1.  // OBJECTIVE-C
2.  #import <XYZ/XYZCustomCell.h>
3.  #import <XYZ/XYZCustomView.h>
4.  #import <XYZ/XYZCustomViewController.h> 

Swift 將會看到所有你在 umbrella header 中公開暴露出來的頭文件,框架 target 中的所有 Swift 文件都可以訪問你 Objective-C 文件的內(nèi)容狼钮,不需要任何 import 語句碳柱。

1.  // SWIFT
2.  let myCell = XYZCustomCell()
3.  myCell.subtitle = "A custom cell" 

將 Swift 導(dǎo)入 Objective-C

要將一些 Swift 文件導(dǎo)入到同個框架的 target 的 Objective-C 代碼去,你不需要導(dǎo)入任何東西到 umbrella header 文件熬芜,而是將 Xcode 為你的 Swift 代碼自動生成的頭文件導(dǎo)入到你的 Obj .m 源文件去莲镣,以便在 Objective-C 代碼中訪問 Swift 代碼。

在同一 framework 中將 Swift 代碼導(dǎo)入到 Objective-C 中

確保將框架 target 的 Build Settings > Packaging 中的 Defines Module 設(shè)置為 Yes涎拉。用下面的語法將 Swift 代碼導(dǎo)入到同個框架 target 下的 Objective-C .m 源文件去瑞侮。

1.  // OBJECTIVE-C
2.  #import <ProductName/ProductModuleName-Swift.h> 

這個 import 語句所包含的 Swift 文件都可以被同個框架 target 下的 Objective-C .m 源文件訪問。關(guān)于在 Objective-C 代碼中使用 Swift 代碼鼓拧,詳見 Using Swift from Objective-C半火。

導(dǎo)入到 Swift 導(dǎo)入到 Swift
Swift 代碼 不需要import語句 #import
Objective-C 代碼 不需要import語句;需要 Objective-C `umbrella頭文件 #import "Header.h"

導(dǎo)入外部 Framework

你可以導(dǎo)入外部框架季俩,不管這個框架是純 Objective-C钮糖,純 Swift,還是混合語言的。import 外部框架的流程都是一樣的店归,不管這個框架是用一種語言寫的阎抒,還是包含兩種語言。當(dāng)你導(dǎo)入外部框架時消痛,確保 Build Setting > Pakaging > Defines Module 設(shè)置為Yes且叁。

用下面的語法將框架導(dǎo)入到不同 target 的 Swift 文件中:

1.  // SWIFT
2.  import FrameworkName 

用下面的語法將框架導(dǎo)入到不同 target 的 Objective-C .m 文件中:

1.  // OBJECTIVE-C
2.  @import FrameworkName; 
導(dǎo)入到 Swift 導(dǎo)入到 Objective-C
任意語言框架 import FrameworkName @import FrameworkName;

在 Objective-C 中使用 Swift

當(dāng)你將 Swift 代碼導(dǎo)入 Objective-C 文件之后,用普通的 Objective-C 語法使用 Swift 類秩伞。


1.  // OBJECTIVE-C

3.  MySwiftClass *swiftObject = [[MySwiftClass alloc] init];
4.  [swiftObject swiftMethod];

Swift 的類或協(xié)議必須用 @Objective-C attribute 來標(biāo)記逞带,以便在 Objective-C 中可訪問。這個 attribute 告訴編譯器這個 Swift 代碼可以從 Objective-C 代碼中訪問纱新。如果你的 Swift 類是 Objective-C 類的子類展氓,編譯器會自動為你添加 @Objective-C attribute。詳見 Swift Type Compatibility怒炸。

你可以訪問 Swift 類或協(xié)議中用 @Objective-C attribute 標(biāo)記過東西带饱,只要它和 Objective-C 兼容。不包括一下這些 Swift 獨(dú)有的特性:

  • Generics - 范型
  • Tuples - 元組
  • Enumerations defined in Swift - Swift 中定義的枚舉
  • Structures defined in Swift - Swift 中定義的結(jié)構(gòu)體
  • Top-level functions defined in Swift - Swift Swift 中定義的頂層函數(shù)
  • Global variables defined in Swift - Swift 中定義的全局變量
  • Typealiases defined in Swift - Swift 中定義的類型別名
  • Swift-style variadics - Swift風(fēng)格可變參數(shù)
  • Nested types - 嵌套類型
  • Curried functions - 柯里化后的函數(shù)

例如帶有范型類型作為參數(shù)阅羹,或者返回元組的方法不能在 Objective-C 中使用。

為了避免循環(huán)引用教寂,不要將 Swift 代碼導(dǎo)入到 Objective-C 頭文件中捏鱼。但是你可以在 Objective-C 頭文件中前向聲明(forward declare)一個 Swift 類來使用它,然而,注意不能在 Objective-C 中繼承一個 Swift 類。

在 Objective-C 頭文件中引用 Swift 類

這樣前向聲明 Swift 類:

1.  // OBJECTIVE-C
2.  // MyObjective-CClass.h

4.  @class MySwiftClass;

6.  @interface MyObjective-CClass : NSObject
7.  - (MySwiftClass *)returnSwiftObject;
8.  /* ... */
9.  @end

Product 模塊命名

Xcode 為 Swift 代碼生成的頭文件的名稱猾骡,以及 Xcode 創(chuàng)建的 Objective-C 橋接頭文件名稱翅阵,都是從你的 product 模塊名生成的。默認(rèn)你的 product 模塊名和 product 名一樣淑倾。然而,如果你的 product 名有特殊字符(nonalphanumeric,非數(shù)字藏斩、字母的字符),例如點(diǎn)號却盘,那么它們會被下劃線(_)替換之后作為你的 product 模塊名狰域。如果 product 名以數(shù)字開頭,那么第一個數(shù)字會用下劃線替換掉黄橘。

你可以給 product 模塊名提供一個自定義的名稱兆览,Xcode 會用這個名稱來命名橋接的和自動生成的頭文件。你只需要在修改在build setting 中的 Product Module Name 即可塞关。

問題解決提示

  • 把 Swift 和 Objective-C 文件看作相同的代碼集合抬探,并注意命名沖突;
  • 如果你用框架帆赢,確保 Build Setting > Pakaging > Defines Module 設(shè)置為 Yes小压;
  • 如果你使用 Objective-C 橋接頭文件线梗,確保在 Build Settings 中 Objective-C 橋接頭文件的 build setting 是基于 Swfit 編譯器,即 Code Generation 含有頭文件的路徑场航。這個路徑必須是頭文件自身的路徑缠导,而不是它所在的目錄;
  • Xcode 使用你的 product 模塊名溉痢,而不是 target 名來命名 Objective-C 橋接頭文件和為 Swift 自動生成的頭文件僻造。詳見 Naming Your Product Module
  • 為了在 Objective-C 中可用孩饼, Swift 類必須是 Objective-C 類的子類髓削,或者用 @Objective-C 標(biāo)記;
  • 當(dāng)你將 Swift 導(dǎo)入到 Objective-C 中時镀娶,記住 Objective-C 不會將 Swift 獨(dú)有的特性翻譯成 Objective-C 對應(yīng)的特性立膛。詳見列表Using Swift from Objective-C
  • 如果你在 Swift 代碼中使用你自己的 Objective-C 類型梯码,確保先將對應(yīng)的 Objective-C 頭文件導(dǎo)入到你的 Swift 代碼中宝泵,然后才將 Swift 自動生成的頭文件 import 到 Objective-C .m 源文件中來訪問 Swift 代碼。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末轩娶,一起剝皮案震驚了整個濱河市儿奶,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鳄抒,老刑警劉巖闯捎,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異许溅,居然都是意外死亡瓤鼻,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門贤重,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茬祷,“玉大人,你說我怎么就攤上這事游桩∩龋” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵借卧,是天一觀的道長盹憎。 經(jīng)常有香客問我,道長铐刘,這世上最難降的妖魔是什么陪每? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上檩禾,老公的妹妹穿的比我還像新娘挂签。我一直安慰自己,他們只是感情好盼产,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布饵婆。 她就那樣靜靜地躺著,像睡著了一般戏售。 火紅的嫁衣襯著肌膚如雪侨核。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天灌灾,我揣著相機(jī)與錄音搓译,去河邊找鬼。 笑死锋喜,一個胖子當(dāng)著我的面吹牛些己,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嘿般,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼段标,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了炉奴?” 一聲冷哼從身側(cè)響起怀樟,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盆佣,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體械荷,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡共耍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吨瞎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痹兜。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖颤诀,靈堂內(nèi)的尸體忽然破棺而出字旭,到底是詐尸還是另有隱情,我是刑警寧澤崖叫,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布遗淳,位于F島的核電站,受9級特大地震影響心傀,放射性物質(zhì)發(fā)生泄漏屈暗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望养叛。 院中可真熱鬧种呐,春花似錦、人聲如沸弃甥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽淆攻。三九已至阔墩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卜录,已是汗流浹背戈擒。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留艰毒,地道東北人筐高。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像丑瞧,于是被迫代替她去往敵國和親柑土。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

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