Using Swift with Cocoa and Objective-C--在同個project中使用Swift和在同個project中

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



Swift系列文章由CocoaChina翻譯小組翻譯自蘋果的官方文檔: Using Swift with Cocoa and Objective-C--Swift and Objective-C in the Same Project。本篇譯者:haolloyin( github主頁),敬請勘誤。

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
   
   
   
   
  1. #import "XYZCustomCell.h" 
  2. #import "XYZCustomView.h" 
  3. #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
   
   
   
   
  1. let myCell = XYZCustomCell() 
  2. 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
   
   
   
   
  1.   
  2. #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
   
   
   
   
  1. #import <XYZ/XYZCustomCell.h> 
  2. #import <XYZ/XYZCustomView.h> 
  3. #import <XYZ/XYZCustomViewController.h> 
 
Swift 將會看到所有你在  umbrella header  中公開暴露出來的頭文件,框架 target 中的所有 Swift 文件都可以訪問你 Objc 文件的內容,不需要不論什麼 import 語句。

SWIFT
   
   
   
   
  1. let myCell = XYZCustomCell() 
  2. 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
   
   
   
   
  1. #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
   
   
   
   
  1.   
  2. import FrameworkName 
 
用如下的語法將框架導入到不一樣 target 的 Objc .m 文件裏:
OBJECTIVE-C
   
   
   
   
  1.   
  2. @import FrameworkName; 
 
在Objective-C中使用 Swift

當你將 Swift 代碼導入 Objc 文件以後,用普通的 Objc 語法使用 Swift 類。
OBJECTIVE-C
   
   
   
   
  1.   
  2. MySwiftClass *swiftObject = [[MySwiftClass alloc] init]; 
  3. [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
   
   
   
   
  1. // MyObjcClass.h 
  2.   
  3. @class MySwiftClass; 
  4.   
  5. @interface MyObjcClass : NSObject 
  6. - (MySwiftClass *)returnSwiftObject; 
  7. /* ... */ 
  8. @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 代碼。
相關文章
相關標籤/搜索