這種情況我是在用 CTMediator 時(shí) Swift 與 OC 相互傳值回調(diào)用到的龟劲,記錄一下。
1.OC 給 Swift 用字典傳 Block
1) OC 代碼正常寫
2) Swift 拿到 block 后善炫,需要轉(zhuǎn)為兼容 Swift 的 block
/*
1) 拿到原始 block
*/
let block = params["reslutBlock"]
/*
2) 定義對(duì)應(yīng)類型的 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: 用于傳播非托管對(duì)象引用的類型(不用ARC)
Unmanaged.passRetained : 如果這個(gè)非托管對(duì)象的使用全程,能夠保障被封裝對(duì)象一直存活肩豁,我們就可以使用 passUnretained 方法,對(duì)象的生命周期還歸編譯器管理
Unmanaged.passUnretained : 如果非托管對(duì)象使用周期超過了編譯器認(rèn)為的生命周期辫呻,比如超出作用域清钥,編譯器自動(dòng)插入 release 的 ARC 語義,那么這個(gè)非托管對(duì)象就是一個(gè)野指針了放闺,此時(shí)我們必須手動(dòng) retain 這個(gè)對(duì)象祟昭,也就是使用 passRetained 方法
一旦你手動(dòng) retain 了一個(gè)對(duì)象,就不要忘記 release 掉它怖侦,方法就是調(diào)用非托管對(duì)象的 release 方法从橘,或者用 takeRetainedValue 取出封裝的對(duì)象,并將其管理權(quán)交回 ARC础钠。但注意恰力,一定不要對(duì)一個(gè)用 passUnretained 構(gòu)造的非托管對(duì)象調(diào)用 release 或者 takeRetainedValue,這會(huì)導(dǎo)致原來的對(duì)象被 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)容強(qiáng)轉(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 定義時(shí)的類型一致
*/
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