[Swift A] - Using Swift with Cocoa and Objective-C--Mix and Match

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

 

Mix and Match 概述

Swift與Objective-C文件能夠在一個工程中並存,無論這個工程本來是基於Objective-C仍是Swift。你能夠直接往現有工程中簡單地添加另外一種語言的文件。這種天然的工做流使得建立混合語言的應用或framework target,與用單獨一種語言時同樣簡單。
 
編寫混合語言的工做流程只有一點點區別,這取決於你是在寫應用仍是寫框架。下面描述了用兩種語言在一個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代碼。
 
在同一target中將Objective-C代碼導入到Swift中
 
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 含有頭文件的路徑。這個路徑必須是頭文件自身的路徑,而不是它所在的目錄。
 
這個路徑應該是你工程的相對路徑,相似 Info.plist 在 Build Settings 中指定的路徑。在大多數狀況下,你不須要修改這個設置。
 
在這個橋接頭文件中列出的全部公開的Objective-C 頭文件都會對 Swift 可見。以後當前 target 的全部 Swift 文件均可以使用這些頭文件中的方法,不須要任何import語句。用 Swift 語法使用這些Objective-C代碼,就像使用系統自帶的類同樣。
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 接口包含了它所使用到的全部 Objc 類型。若是你在 Swift 代碼中使用你本身的Objective-C類型,確保先將對應的 Objc 頭文件導入到你的 Swift 代碼中,而後纔將 Swift 自動生成的頭文件導入到 Objc .m 源文件中來訪問 Swift 代碼。
 
在同一target中將Swift代碼導入到Objective-C中 
 
在相同 target 的 Objc .m 源文件中,用下面的語法來導入Swift 代碼:
OBJECTIVE-C
#import 「ProductModuleName-Swift.h」 

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

在同個Framework Target中導入代碼

若是你在寫一個混合語言的框架,可能會從 Swift 代碼訪問 Objc 代碼,或者反之。
 
將 Objc 導入 Swift
要將一些 Objc 文件導入到同個框架 target 的 Swift 代碼中去,你須要將這些文件導入到 Objc 的  umbrella header  來供框架使用。
 
在同一framework中將Objective-C代碼導入到Swift中
 
確保將框架 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 代碼。
 
在同一framework中將Swift代碼導入到Objective-C中
 
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-Cgit

導入外部 Framework

你能夠導入外部框架,無論這個框架是純 Objc,純 Swift,仍是混合語言的。import 外部框架的流程都是同樣的,無論這個框架是用一種語言寫的,仍是包含兩種語言。當你導入外部框架時,確保  Build Setting > Pakaging > Defines Module  設置爲  Yes 。
 
用下面的語法將框架導入到不一樣 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 類。
 
在Objective-C頭文件中引用Swift類
 
這樣前向聲明 Swift 類:
OBJECTIVE-C
// MyObjcClass.h 
  
@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 代碼。
 
 
本章由CocoaChina的翻譯小組成員  haolloyin( github主頁 翻譯,轉載請註明出處和譯者信息,拒絕商業之用。

 http://www.cocoachina.com/newbie/basic/2014/0605/8688.htmlgithub

 https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html#//apple_ref/doc/uid/TP40014216-CH10-XID_85swift

相關文章
相關標籤/搜索