一. 在同一個(gè)app或者Unit Test混編
我們先建兩個(gè)文件, 一個(gè)oc, 一個(gè)swift
@interface FirstOC : NSObject
- (void)logOC;
@end
@implementation FirstOC
- (void)logOC {
NSLog(@"%@", _cmd);
}
@end
class FirstSwift : NSObject {
@objc func logSwift() {
print(#function)
}
}
1.1 oc調(diào)用swift
我們需要在oc文件里面這樣使用, 導(dǎo)入#import "hybirdTest-Swift.h"就能使用使用swift這個(gè)類(lèi)了。 其中hybirdTest是項(xiàng)目名稱(chēng),-Swift.h是固定后綴。
#import "hybirdTest-Swift.h"
1.1.1 為啥呢?
打開(kāi)看看, 搜索FirstSwift,發(fā)現(xiàn)xcode將swift代碼導(dǎo)出為oc的方法聲明,這樣就能編譯通過(guò)了。
圖片.png
1.2 swift調(diào)用oc
我們需要在hybirdTest-Bridging-Header中導(dǎo)入swift類(lèi)需要用到的OC類(lèi), 這樣就可以做到swift調(diào)用oc了。
圖片.png
1.2.1 為啥呢?
具體實(shí)現(xiàn)不詳, 猜測(cè)是找到SWIFT_OBJC_BRIDGING_HEADER這個(gè)環(huán)境變量,然后將其中的OC代碼導(dǎo)出為swift的聲明
圖片.png
二. 不同組件或者同一組件之間的混編
早些時(shí)候都是主工程和組件都是OC代碼的時(shí)候, 我們要使用組件代碼,只需要`#import<A/A.h>即可。
但是后來(lái)swift的比重越來(lái)越大, 怎么引用組件中swift的代碼就成了一個(gè)問(wèn)題。
2.1 頭文件的各種導(dǎo)入方式
- #include:C/C++導(dǎo)入頭文件的關(guān)鍵字, 原理是簡(jiǎn)單粗暴的將要導(dǎo)入的文件代碼復(fù)制到當(dāng)前文件,會(huì)導(dǎo)致重復(fù)導(dǎo)入,效率低下
- #import:OC的頭文件導(dǎo)入方式,它能保證同一個(gè)頭文件不會(huì)被重復(fù)包含
- @class: 告訴編譯期我有這個(gè)類(lèi),先別急著報(bào)錯(cuò),我會(huì)在稍后的文件里#import具體的類(lèi)實(shí)現(xiàn)的,可以解決頭文件的相互包含的問(wèn)題
- @import: OC中用來(lái)導(dǎo)入模塊的方式
- import: swift中用來(lái)導(dǎo)入模塊的方式
2.2 search paths
- Header search paths:和下面的差不多,如果編譯器不支持user headers概念,會(huì)從header search paths中去尋找
- user header search paths:和上面差不多
- use header maps:生成hmap文件,記錄了頭文件名稱(chēng)及其對(duì)應(yīng)的磁盤(pán)位置
- 上面3個(gè)一般配合使用
- Enable Modules: 允許使用模塊,也就是可以使用@import和import
2.3 組件A引用混編的組件B失敗
在A的podspec中添加以下代碼
search_paths = ["\"${PODS_ROOT}/Headers/Public/ZZUI\"",
"\"${PODS_ROOT}/Headers/Private/ZZUI\"",
]
ss.pod_target_xcconfig = {
'HEADER_SEARCH_PATHS' => search_paths.join(' '),
'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES'
}
對(duì)比下xcconfig, 發(fā)現(xiàn)HEADER_SEARCH_PATHS多了ZZUI,這樣就能找到了。
//加了代碼
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/ModuleSearchFilter" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/SQLiteRepairKit" "${PODS_ROOT}/Headers/Public/WCDB" "${PODS_ROOT}/Headers/Public/WCDBOptimizedSQLCipher" "${PODS_ROOT}/Headers/Public/ZZUI" "${PODS_ROOT}/Headers/Private/ZZUI"
//沒(méi)加代碼
HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/ModuleSearchFilter" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/SQLiteRepairKit" "${PODS_ROOT}/Headers/Public/WCDB" "${PODS_ROOT}/Headers/Public/WCDBOptimizedSQLCipher"
2.4 SWIFT_INCLUDE_PATHS
需要注意的點(diǎn):
引用組件文件的時(shí)候,盡量不要使用import"", 這樣會(huì)導(dǎo)致開(kāi)啟module的時(shí)候報(bào)錯(cuò)
參考:
綜合篇
clang官網(wǎng)中的module實(shí)現(xiàn)
oc swift的api交互
詳解
錯(cuò)誤排查
實(shí)戰(zhàn)一下



