Swift與Objective-C的兼容能力贊成你在同一個project中同一時候使用兩種語言。你可以用這樣的叫作「mix and match」的特性來開發基於混合語言的應用。使用Swfit的最新特性--「mix and match」。你可以實現應用的一部分功能,並沒有縫地併入已有的Objective-C的代碼中。
Mix and Match 概述
Swift與Objective-C文件可以在一個project中並存,不管這個project本來是基於Objective-C仍是Swift。
你可以直接往現有project中簡單地加入還有一種語言的文件。這樣的天然的工做流使得建立混合語言的應用或framework target,與用單獨一種語言時同樣簡單。ios
編寫混合語言的工做流程僅僅有一點點差異。這取決於你是在寫應用仍是寫框架。如下描寫敘述了用兩種語言在一個target中導入模型的狀況,興許章節會有不少其它細節。
在同一個App Target中進行代碼導入
假設你在寫混合語言的應用,可能需要用Swift代碼訪問Objective-C代碼。或者反之。本章描寫敘述的流程適用於non-framework target。
將Objective-C導入Swift
要在同一個app target中導入Objective-C文件供Swift使用,你需要依賴Objective-C的橋接頭文件(Objective-C bridging header)來暴露給 Swift。當你加入 Swift 文件到現有的Objective-C應用時,Xcode 會本身主動建立這些頭文件,反之亦然。
假設你容許,Xcode 會在源文件建立的同一時候生成頭文件,並用product的模塊名加上 -Bridging-Header.h命名。關於 product 的模塊名,詳見 Naming Your Product Module。
你應該編輯這個頭文件來對Swift暴露出Objective-C代碼。
To import Objective-C code into Swift from the same target
1.在Objective-C橋接頭文件裏,導入不論什麼你想暴露給 Swift 的頭文件。好比:
OBJECTIVE-C
- #import "XYZCustomCell.h"
- #import "XYZCustomView.h"
- #import "XYZCustomViewController.h"
2.在Build Settings中,確保Objective-C橋接頭文件的build setting是基於 Swfit 編譯器,即Code Generation 含有頭文件的路徑。
這個路徑必須是頭文件自身的路徑。而不是它所在的文件夾。git
這個路徑應該是你project的相對路徑,相似 Info.plist 在 Build Settings 中指定的路徑。在大多數狀況下,你不需要改動這個設置。
在這個橋接頭文件裏列出的所有公開的Objective-C 頭文件都會對 Swift 可見。
以後當前 target 的所有 Swift 文件都可以使用這些頭文件裏的方法,不需要不論什麼import語句。github
用 Swift 語法使用這些Objective-C代碼,就像使用系統自帶的類同樣。swift
SWIFT
- let myCell = XYZCustomCell()
- myCell.subtitle = "A custom cell"
將 Swift 導入Objective-C
向Objective-C中導入Swift代碼時,你依賴 Xcode 生成的頭文件來向Objective-C暴露 Swift 代碼。這個本身主動生成Objective-C頭文件,聲明瞭target 中所有 Swift 代碼中定義的接口。可以把這個Objective-C頭文件看做 Swift 代碼的umbrella header。
它以 product 模塊名加 -Swift.h 來命名。關於 product 的模塊名,詳見 Naming Your Product Module。app
你不需要作不論什麼事情來生成這個頭文件。僅僅需要將它導入到你的Objective-C代碼來使用它。注意這個頭文件裏的 Swift 接口包括了它所使用到的所有 Objc 類型。
假設你在 Swift 代碼中使用你本身的Objective-C類型,確保先將相應的 Objc 頭文件導入到你的 Swift 代碼中,而後纔將 Swift 本身主動生成的頭文件導入到 Objc .m 源文件裏來訪問 Swift 代碼。框架
To import Swift code into Objective-C from the same target
在一樣 target 的 Objc .m 源文件裏。用如下的語法來導入Swift 代碼:
OBJECTIVE-C
-
- #import 「ProductModuleName-Swift.h」
target 中不論什麼 Swift 文件將會對 Objc .m 文件可見,包含這個 import 語句。
關於在 Objc 代碼中使用 Swift 代碼。詳見 Using Swift from Objective-C。ide
在同個Framework Target中導入代碼
假設你在寫一個混合語言的框架,可能會從 Swift 代碼訪問 Objc 代碼。或者反之。
將 Objc 導入 Swift
要將一些 Objc 文件導入到同個框架 target 的 Swift 代碼中去。你需要將這些文件導入到 Objc 的 umbrella header 來供框架使用。
To import Objective-C code into Swift from the same framework
確保將框架 target 的 Build Settings > Packaging > Defines Module 設置爲 Yes 。而後在你的 umbrella header 頭文件裏導入你想暴露給 Swift 訪問的 Objc 頭文件,好比:
OBJECTIVE-C
- #import <XYZ/XYZCustomCell.h>
- #import <XYZ/XYZCustomView.h>
- #import <XYZ/XYZCustomViewController.h>
Swift 將會看到所有你在 umbrella header 中公開暴露出來的頭文件,框架 target 中的所有 Swift 文件都可以訪問你 Objc 文件的內容,不需要不論什麼 import 語句。
SWIFT
- let myCell = XYZCustomCell()
- myCell.subtitle = "A custom cell"
將 Swift 導入 Objc
要將一些 Swift 文件導入到同個框架的 target 的 Objc 代碼去,你不需要導入不論什麼東西到umbrella header文件,而是將 Xcode 爲你的Swift代碼本身主動生成的頭文件導入到你的 Obj .m 源文件去。以便在 Objc 代碼中訪問 Swift 代碼。
To import Swift code into Objective-C from the same framework
1.確保將框架target 的 Build Settings > Packaging 中的 Defines Module 設置爲 Yes 。用如下的語法將 Swift 代碼導入到同個框架 target 下的 Objc .m 源文件去。
OBJECTIVE-C
- #import <ProductName/ProductModuleName-Swift.h>
這個 import 語句所包括的 Swift 文件都可以被同個框架 target 下的 Objc .m 源文件訪問。關於在 Objc 代碼中使用 Swift 代碼。詳見 Using Swift from Objective-C。
導入外部 Framework
你可以導入外部框架,不管這個框架是純 Objc,純 Swift。仍是混合語言的。
import 外部框架的流程都是同樣的,不管這個框架是用一種語言寫的,仍是包括兩種語言。函數
當你導入外部框架時,確保 Build Setting > Pakaging > Defines Module 設置爲 Yes 。ui
用如下的語法將框架導入到不一樣 target 的 Swift 文件裏:
SWIFT
-
- import FrameworkName
用如下的語法將框架導入到不一樣 target 的 Objc .m 文件裏:
OBJECTIVE-C
-
- @import FrameworkName;
在Objective-C中使用 Swift
當你將 Swift 代碼導入 Objc 文件以後,用普通的 Objc 語法使用 Swift 類。
OBJECTIVE-C
-
- MySwiftClass *swiftObject = [[MySwiftClass alloc] init];
- [swiftObject swiftMethod];
Swift 的類或協議必須用 @objc attribute 來標記。以便在 Objc 中可訪問。
這個 attribute 告訴編譯器這個 Swift 代碼可以從 Objc 代碼中訪問。假設你的 Swift 類是 Objc 類的子類,編譯器會本身主動爲你加入 @objc attribute 。
詳見 Swift Type Compatibility。
你可以訪問 Swift 類或協議中用 @objc attribute 標記過東西,僅僅要它和 Objc 兼容。
不包含一下這些 Swift 獨有的特性:
Generics - 範型
Tuples - 元組
Enumerations defined in Swift - Swift 中定義的枚舉
Structures defined in Swift - Swift 中定義的結構體
Top-level functions defined in Swift - Swift Swift 中定義的頂層函數
Global variables defined in Swift - Swift 中定義的全局變量
Typealiases defined in Swift - Swift 中定義的類型別名
Swift-style variadics
Nested types - 嵌套類型
Curried functions - 柯里化後的函數
好比帶有範型類型做爲參數,或者返回元組的方法不能在Objective-C中使用。
爲了不循環引用,不要將 Swift 代碼導入到Objective-C頭文件裏。但是你可以在Objective-C頭文件裏前向聲明( forward declare )一個 Swift 類來使用它。然而。注意不能在Objective-C中繼承一個 Swift 類。
To reference a Swift class in an Objective-C header file
這樣前向聲明 Swift 類:
OBJECTIVE-C
-
-
- @class MySwiftClass;
-
- @interface MyObjcClass : NSObject
- - (MySwiftClass *)returnSwiftObject;
-
- @end
Product Module命名
Xcode 爲 Swift 代碼生成的頭文件的名稱。以及 Xcode 建立的 Objc 橋接頭文件名,都是從你的 product 模塊名生成的。默認你的 product 模塊名和 product 名同樣。然而,假設你的 product 名有特殊字符(nonalphanumeric,非數字、字母的字符)。好比點號,那麼它們會被下劃線( _ )替換以後做爲你的 product 模塊名。假設 product 名以數字開頭,那麼第一個數字會用下劃線替換掉。
你可以給 product 模塊名提供一個本身定義的名稱,Xcode 會用這個名稱來命名橋接的和本身主動生成的頭文件。你僅僅需要在改動在 build setting 中的 Product Module Name 就能夠。
故障建議和提醒
•把 Swift 和 Objc 文件看做一樣的代碼集合,並注意命名衝突;
•假設你用框架,確保 Build Setting > Pakaging > Defines Module 設置爲 Yes 。
•假設你使用 Objc 橋接頭文件。確保在 Build Settings 中 Objc 橋接頭文件的 build setting 是基於 Swfit 編譯器,即 Code Generation 含有頭文件的路徑。這個路徑必須是頭文件自身的路徑,而不是它所在的文件夾。
•Xcode 使用你的 product 模塊名。而不是 target 名來命名 Objc 橋接頭文件和爲 Swift 本身主動生成的頭文件。詳見 Naming Your Product Module;
•爲了在 Objc 中可用, Swift 類必須是 Objc 類的子類,或者用 @objc 標記;
•當你將 Swift 導入到 Objc 中時,記住 Objc 不會將 Swift 獨有的特性翻譯成 Objc 相應的特性。詳見列表 Using Swift from Objective-C;
•假設你在 Swift 代碼中使用你本身的 Objc 類型,確保先將相應的 Objc 頭文件導入到你的 Swift 代碼中。而後纔將 Swift 本身主動生成的頭文件 import 到 Objc .m 源文件裏來訪問 Swift 代碼。