Daniele Levis Pelusi on Unsplash
#前言
最近開始工作,公司專案本身是以 objective-C 開發,想慢慢轉型成 Swift,因此需要在 objective-C 專案中加入 Swift,而在嘗試的過程中也發生了一些小問題,今天就來看下混編可能會遇到的種種事吧。
#介紹
混編無非就是兩種情況:
- 在 objective-C 中調用 Swift
- 在 Swift 中調用 objective-C
在這過程中有兩個關鍵的文件:
- 橋接文件:”ProjectName-Bridging-Header.h”
- Objective-C Generated Interface Header Name 文件:”ProductModuleName-Swift.h”
#主要文件
橋接文件
- 用途:Swift 調用 Objective-C Class 時使用,可以暴露 Objective-C files 給 Swift
- 用法:在裡頭
#import “xxx.h”
,Swift 即可使用 - 如何叫出:當在 Objective-C app 中加入 Swift file 或者在 Swift app 中加入 Objective-C file,Xcode 就會提供創建
Objective-C Generated Interface Header Name 文件
- 用途:Objective-C 調用 Swift Class 時使用,該 file 是一個 Objective-C header,用來聲明 Swift interfaces,可以當作是 Swift code 的 umbrella header
- 用法:在想導入 Swift 的 Objective-C Class 中
#import “ProductModuleName-Swift.h”
,即可使用 Swift - 如何叫出:同 橋接文件
#實作
自動創建 Bridging Header
在 OC Project 中創建 Swift Class 會跳出視窗,如下:
點選 Create Bridging Header
會產生 ProjectName-Bridging-Header.h
,只有第一次生成 Swift Class 會出現。
同時在 Build Settings
裡會產生 Swift Compiler
配置:
如果點了 Don't Create
,將不會產生 OC Practice-Bridging-Header.h
, Swift Compiler
也不會有 Header Nam
,需要自行創建並配好路徑。
注意:確認 Info.plist 的路徑名稱跟 Bridging Header 是否一致的,大多情況下是相同的。
手動創建 Bridging Header
- 加入 header file:File >New > File > (Source) Header File. 檔案名稱通常設成
ProjectName
-Bridging-Header.
然後 create,不需要勾選任何的 target。 - 之後到 Target > Build Settings 尋找 Swift Compiler — General. 裡頭有 Objective-C Bridging Header 然後設置路徑,如果路徑不會設置可以參考可能遇到的問題。
在 Objective-C 中調用 Swift
- Swift Class 的 property 和 function 需在前面加上
@objc
,Objective-C 才能抓到
注意!! Class 一定要有繼承,不然 Objective-C 會抓不到
2. 在任何 Objective-C .m file
中要先 #import “ProductModuleName-Swift.h”
3. 最後就可以在 Objective-C 中使用 Swift Class
用 private 或 fileprivate 修飾的聲明將不會出現在 generated header,並且不會在 Objective-C runtime 時暴露,除非帶有 @IBAction
, @IBOutlet
, or @objc
屬性。
在 Swift 中調用 Objective-C
- 在
ProjectName-Bridging-Header.h
裡 importSwift 要調用的 Objective-C class
2. Swift 可以直接使用 import 的 Objective-C class
Swift 調用就簡單很多。
#可能遇到的問題
找不到 Swift Compiler
這意味著這 Project 還沒有 Swift file。在新增時記得所有 target 都要點選,不然會有 Swift 檔案有些 target 不能用的問題。
手動新增 Bridging Header 找不到位置
位置必須從有 .xcodeproj 這一層開始算起,如下圖
當有多個 targets,該如果處理 import “TargetName-Swift.h”
每個 target都有屬於自己的
Interface Header Name
,不可能每換一個target就重打一次import,但又不能一口氣 import所有 Interface Header Name
,除了當前 target 的 Interface Header Name
外,其他都會報錯。
解決方法:統一
Interface Header Name
的名稱
將 $(SWIFT_MODULE_NAME)-Swift.h
改成 $(PROJECT_NAME)-Swift.h
project 是同一個,因此不同 target 會有相同的 Interface Header Name
https://stackoverflow.com/questions/26262029/objective-c-to-swift-header-file-with-multiple-targets
#補充
ProductModuleName-Swift.h 究竟是什麼呢?
ProductModuleName-Swift.h
是一個自動生成的頭文件,沒有對應的 code,可以試著 Commend+LeftClick
進去看裡頭。
在 Swift Class 中加入的 property 和 function,都在OC_Practice-Swift.h
產生對應的OC 接口,因此可以通過 OC_Practice-Swift.h
去調用這些接口。
注意!!如果 Swift 的 property 和 function 前面沒有加上 @objc 就不會產生接口,因此 Objective-C 會抓不到。