Swift 與 OC 用字典互傳 Block

這種情況我是在用 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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容