這種情況我是在用 CTMediator 時 Swift 與 OC 相互傳值回調(diào)用到的,記錄一下。
1.OC 給 Swift 用字典傳 Block
1) OC 代碼正常寫
2) Swift 拿到 block 后,需要轉(zhuǎn)為兼容 Swift 的 block
/*
1) 拿到原始 block
*/
let block = params["reslutBlock"]
/*
2) 定義對應類型的 block 別名,用 @convention(block) 修飾
@convention(swift) block類型 :聲明這是swift block
@convention(block) block類型 :聲明這是兼容swift | oc 的 block
@convention(c) block類型 :聲明這是c block
BlockType : 別名
(NSString) -> Void : 傳入的 block 類型
*/
typealias BlockType = @convention(block) (NSString) -> Void
/*
3) 獲取 block 的內(nèi)存地址
Unmanaged: 用于傳播非托管對象引用的類型(不用ARC)
Unmanaged.passRetained : 如果這個非托管對象的使用全程,能夠保障被封裝對象一直存活,我們就可以使用 passUnretained 方法,對象的生命周期還歸編譯器管理
Unmanaged.passUnretained : 如果非托管對象使用周期超過了編譯器認為的生命周期,比如超出作用域,編譯器自動插入 release 的 ARC 語義,那么這個非托管對象就是一個野指針了,此時我們必須手動 retain 這個對象,也就是使用 passRetained 方法
一旦你手動 retain 了一個對象,就不要忘記 release 掉它,方法就是調(diào)用非托管對象的 release 方法,或者用 takeRetainedValue 取出封裝的對象,并將其管理權(quán)交回 ARC。但注意,一定不要對一個用 passUnretained 構(gòu)造的非托管對象調(diào)用 release 或者 takeRetainedValue,這會導致原來的對象被 release 掉,從而引發(fā)異常。
*/
let blockPtr = UnsafeRawPointer(Unmanaged<AnyObject>.passUnretained(block as AnyObject).toOpaque())
/*
4) 根據(jù) 2.3 的內(nèi)存地址將內(nèi)存里的內(nèi)容轉(zhuǎn)為 2.2 定義的類型
unsafeBitCast(x, to: type) :將x內(nèi)存地址的內(nèi)容強轉(zhuǎn)為 type 類型的內(nèi)容
blockPtr : 地址
BlockType : block 類型
*/
let newBlock = unsafeBitCast(blockPtr, to: BlockType.self)
2.Swift 給 OC 用字典傳 Block
1) OC 代碼正常寫
2) Swift 先把 block_1 轉(zhuǎn)化為 兼容 Swift | OC 的 block _2
再將 block _2 轉(zhuǎn)化為 AnyObject 傳入字典
/*
1) 定義 block
(String) -> Void :自定義類型
*/
let block: (String) -> Void = { param in
// 業(yè)務(wù)邏輯
}
/*
2) 將 block 轉(zhuǎn)化為兼容 Swift | OC 的 block
(String) -> Void : block 類型
注意: 這里的 block 類型需要與 2.1 定義時的類型一致
*/
let compatibilityBlock = block as @convention(block) (String) -> Void
/*
3) 將兼容 block 轉(zhuǎn)化為 AnyObject
*/
let compatibilityBlockObject = unsafeBitCast(compatibilityBlock, to: AnyObject.self)
/*
4) 作為參數(shù)保存
*/
let param = [
"reslutBlock" : compatibilityBlockObject,
] as [String : Any]
參考:
swift的@convention
Swift-Unmanaged使用
[Swift] 指針UnsafePointer