在一個項目中同時使用Swift和Objective-C代碼混合編程的方法

主要介紹了在一個項目中同時使用Swift和Objective-C代碼的方法,在一個工程中同時使用Swift和Objective-C混合語言編程的方法.html

 

 

Swift 與 Objective-C 的兼容能力使你能夠在同一個工程中同時使用兩種語言。你能夠用這種叫作 mix and match 的特性來開發基於混合語言的應用,能夠用 Swfit 的最新特性實現應用的一部分功能,並沒有縫地併入已有的 Objective-C 的代碼中。ios

Mix and Match 概述編程

Objective-C 和 Swift 文件能夠在一個工程中並存,無論這個工程本來是基於 Objective-C 仍是 Swift。你能夠直接往現有工程中簡單地添加另外一種語言的源文件。這種天然的工做流使得建立混合語言的應用或框架 target,與用單獨一種語言時同樣簡單。swift

混合語言的工做流程只有一點點區別,這取決於你是在寫應用仍是寫框架。下面描述了普通的用兩種語言在一個 target 中導入模型的狀況,後續章節會有更多細節。app

在同個應用的 target 中導入框架

若是你在寫混合語言的應用,可能須要用 Swift 代碼訪問 Objective-C 代碼,或者反之。下面的流程描述了在非框架 target 中的應用。函數

將 Objective-C 導入 Swiftui

在一個應用的 target 中導入一些 Objective-C 文件供 Swift 代碼使用時,你須要依賴與 Objective-C 的橋接頭文件(bridging header)來暴露給 Swift。當你添加 Swift 文件到現有的 Objective-C 應用(或反之)時,Xcode 會自動建立這些頭文件。spa

若是你贊成,Xcode 會在源文件建立的同時生成頭文件,並用 product 的模塊名加上 -Bridging-Header.h 命名。關於 product 的模塊名,詳見 Naming Your Product Module。翻譯

你應該編輯這個頭文件來對 Swift 暴露出 Objective-C 代碼。

在同一 target 中將 Objective-C 代碼導入到 Swift 中

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

複製代碼 代碼以下:

// OBJECTIVE-C

#import "XYZCustomCell.h"
#import "XYZCustomView.h"
#import "XYZCustomViewController.h"

2) 確保在 Build Settings 中 Objective-C 橋接頭文件的 build setting 是基於 Swfit 編譯器,即 Code Generation 含有頭文件的路徑。這個路徑必須是頭文件自身的路徑,而不是它所在的目錄。

這個路徑應該是你工程的相對路徑,相似 Info.plist 在 Build Settings 中指定的路徑。在大多數狀況下,你不須要修改這個設置。

在這個橋接頭文件中列出的全部 public 的 Objective-C 頭文件都會對 Swift 可見。以後當前 target 的全部 Swift 文件均可以使用這些頭文件中的方法,不須要任何 import 語句。用 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。

你不須要作任何事情來生成這個頭文件,只須要將它導入到你的 Objective-C 代碼來使用它。注意這個頭文件中的 Swift 接口包含了它所使用到的全部 Objective-C 類型。若是你在 Swift 代碼中使用你本身的 Objective-C 類型,確保先將對應的 Objective-C 頭文件導入到你的 Swift 代碼中,而後纔將 Swift 自動生成的頭文件導入到 Objective-C .m 源文件中來訪問 Swift 代碼。

在同一 target 中將 Swift 代碼導入到 Objective-C 中

在相同 target 的 Objective-C .m 源文件中,用下面的語法來導入Swift 代碼:

複製代碼 代碼以下:

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

target 中任何 Swift 文件將會對 Objective-C .m 源文件可見,包括這個 import 語句。關於在 Objective-C 代碼中使用 Swift 代碼,詳見 Using Swift from Objective-C

 

  導入到 Swift 導入到 Swift
Swift 代碼 不須要import語句 #import
Objective-C 代碼 不須要import語句;須要 Objective-C `umbrella頭文件 #import "Header.h"

在同個 Framework 的 target 中導入

若是你在寫一個混合語言的框架,可能會從 Swift 代碼訪問 Objective-C 代碼,或者反之。

將 Objective-C 導入 Swift

要將一些 Objective-C 文件導入到同個框架 target 的 Swift 代碼中去,你須要將這些文件導入到 Objective-C 的 umbrella header來供框架使用。

在同一 framework 中將 Objective-C 代碼導入到 Swift 中

確保將框架 target 的 Build Settings > Packaging > Defines Module 設置爲 Yes。而後在你的 umbrella header 頭文件中導入你想暴露給 Swift 訪問的 Objective-C 頭文件,例如:

複製代碼 代碼以下:

// OBJECTIVE-C
#import <XYZ/XYZCustomCell.h>
#import <XYZ/XYZCustomView.h>
#import <XYZ/XYZCustomViewController.h>

Swift 將會看到全部你在 umbrella header 中公開暴露出來的頭文件,框架 target 中的全部 Swift 文件均可以訪問你 Objective-C 文件的內容,不須要任何 import 語句。

複製代碼 代碼以下:

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

將 Swift 導入 Objective-C

要將一些 Swift 文件導入到同個框架的 target 的 Objective-C 代碼去,你不須要導入任何東西到 umbrella header 文件,而是將 Xcode 爲你的 Swift 代碼自動生成的頭文件導入到你的 Obj .m 源文件去,以便在 Objective-C 代碼中訪問 Swift 代碼。

在同一 framework 中將 Swift 代碼導入到 Objective-C 中

確保將框架 target 的 Build Settings > Packaging 中的 Defines Module 設置爲 Yes。用下面的語法將 Swift 代碼導入到同個框架 target 下的 Objective-C .m 源文件去。

複製代碼 代碼以下:

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

這個 import 語句所包含的 Swift 文件均可以被同個框架 target 下的 Objective-C .m 源文件訪問。關於在 Objective-C 代碼中使用 Swift 代碼,詳見 Using Swift from Objective-C

 

  導入到 Swift 導入到 Swift
Swift 代碼 不須要import語句 #import
Objective-C 代碼 不須要import語句;須要 Objective-C `umbrella頭文件 #import "Header.h"

在 Objective-C 中使用 Swift

當你將 Swift 代碼導入 Objective-C 文件以後,用普通的 Objective-C 語法使用 Swift 類。

複製代碼 代碼以下:

// OBJECTIVE-C

MySwiftClass *swiftObject = [[MySwiftClass alloc] init];
[swiftObject swiftMethod];

Swift 的類或協議必須用 @Objective-C attribute 來標記,以便在 Objective-C 中可訪問。這個 attribute 告訴編譯器這個 Swift 代碼能夠從 Objective-C 代碼中訪問。若是你的 Swift 類是 Objective-C 類的子類,編譯器會自動爲你添加 @Objective-C attribute。詳見 Swift Type Compatibility

你能夠訪問 Swift 類或協議中用 @Objective-C attribute 標記過東西,只要它和 Objective-C 兼容。不包括一下這些 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 - Swift風格可變參數
•Nested types - 嵌套類型
•Curried functions - 柯里化後的函數

例如帶有範型類型做爲參數,或者返回元組的方法不能在 Objective-C 中使用。

爲了不循環引用,不要將 Swift 代碼導入到 Objective-C 頭文件中。可是你能夠在 Objective-C 頭文件中前向聲明(forward declare)一個 Swift 類來使用它,然而,注意不能在 Objective-C 中繼承一個 Swift 類。

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

這樣前向聲明 Swift 類:

複製代碼 代碼以下:

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

@class MySwiftClass;

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

Product 模塊命名

Xcode 爲 Swift 代碼生成的頭文件的名稱,以及 Xcode 建立的 Objective-C 橋接頭文件名稱,都是從你的 product 模塊名生成的。默認你的 product 模塊名和 product 名同樣。然而,若是你的 product 名有特殊字符(nonalphanumeric,非數字、字母的字符),例如點號,那麼它們會被下劃線(_)替換以後做爲你的 product 模塊名。若是 product 名以數字開頭,那麼第一個數字會用下劃線替換掉。

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

問題解決提示

•把 Swift 和 Objective-C 文件看做相同的代碼集合,並注意命名衝突; •若是你用框架,確保 Build Setting > Pakaging > Defines Module 設置爲 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 標記; •當你將 Swift 導入到 Objective-C 中時,記住 Objective-C 不會將 Swift 獨有的特性翻譯成 Objective-C 對應的特性。詳見列表Using Swift from Objective-C; •若是你在 Swift 代碼中使用你本身的 Objective-C 類型,確保先將對應的 Objective-C 頭文件導入到你的 Swift 代碼中,而後纔將 Swift 自動生成的頭文件 import 到 Objective-C .m 源文件中來訪問 Swift 代碼。

相關文章
相關標籤/搜索