Swift 和OC的blcok属性不一致问题

组件之间进行属性传值的时候,如果通过CTMediator来进行block传值,swift和OC间就会出现block的传值类型不一致,导致报错问题。
这里我们可以利用convention 字段来进行相关转换

此特性用于修饰一个函数对象的类型,以指 定其调用约定。Swift一共有三种调用约定:

(1)swift:用于指示该函数对象为一个 Swift函数的引用。这也是Swift编程语言的标准 函数调用约定。

(2)block:用于指示该函数对象与 Objective-C的Block引用相兼容。也就是说,它 是一个与Objective-C中的 id 相兼容的Objective-C对象,该Block对象将其函数调用嵌 入在其对象内。而内部的函数调用则用的是C调用约定。

(3)c:用于指示该函数对象是一个C函数 的引用。也就是说,该函数引用不带任何执行 上下文,并且直接使用C语言函数调用约定。这 意味着此函数对象可以与C语言中的函数指针进 行直接交互。我们在第22章中会做详细介绍。

我们下面来看些简单的例子。

func test() {
    var x = 100
/// ref1具有Swift标准函数调用约定,
/// 它可以对一个捕获局部对象的闭包进行引用 let ref1: @convention(swift) (Int) ->
Void = {
        (a: Int) -> Void in
x += a }
/// ref2具有block调用约定,
/// 它可以直接与Objective-C中的Block进行交 互,
/// 同时也能作为一个Objective-C的对象进行使用
    let ref2: @convention(block) (Int) ->
Void = {
        (a: Int) -> Void in
x -= a }
/// ref3具有C函数调用约定,
/// ref3不能引用一个捕获局部对象的闭包,
/// 因为普通的C函数没有自己的执行上下文,
/// 因此无法对局部对象的捕获做任何处理
let ref3: @convention(c) (Int) -> Void =
    ref1(10)
    ref2(5)
    ref3(1)
    print("x = \(x)")
}
test()

ok,convention字段介绍完了,我们这里就用到了它的block调用约定

  /*
         1、 拿到OC传过来的 block 属性
         */
        let parBlock = params["block"]
        
        /*
         2、 定义对应类型的 block 别名,用 @convention(block) 修饰
         @convention(swift) block类型 :声明这是swift block
         @convention(block) block类型 :声明这是兼容swift | oc 的 block
         @convention(c)     block类型 :声明这是c block
     
         BlockType       : 别名
         ((Dictionary) -> Void : 传入swift中的 block 类型
         */
        typealias BlockType = @convention(block) (Dictionary) -> Void
     
        /*
         3、 获取 parBlock 的内存地址
         Unmanaged: 用于传播非托管对象引用的类型(不用ARC)
         Unmanaged.passRetained       : 如果这个非托管对象的使用全程,能够保障被封装对象一直存活,我们就可以使用 passUnretained 方法,对象的生命周期还归编译器管理
         Unmanaged.passUnretained     : 如果非托管对象使用周期超过了编译器认为的生命周期,比如超出作用域,编译器自动插入 release 的 ARC 语义,那么这个非托管对象就是一个野指针了,此时我们必须手动 retain 这个对象,也就是使用 passRetained 方法
         一旦你手动 retain 了一个对象,就不要忘记 release 掉它,方法就是调用非托管对象的 release 方法,或者用 takeRetainedValue 取出封装的对象,并将其管理权交回 ARC。但注意,一定不要对一个用 passUnretained 构造的非托管对象调用 release 或者 takeRetainedValue,这会导致原来的对象被 release 掉,从而引发异常。
        */
        let blockPtr = UnsafeRawPointer(Unmanaged.passUnretained(parBlock as AnyObject).toOpaque())
     
        /*
         4、 根据 3 的内存地址将内存里的内容转为 2 定义的类型
         unsafeBitCast(x, to: type) :将x内存地址的内容强转为 type 类型的内容
     
         blockPtr     : 地址
         BlockType : block 类型
         */
        let newBlock = unsafeBitCast(blockPtr, to: BlockType.self)

最后,将我们得到的newBlock赋值给swift中的Block就搞定啦

你可能感兴趣的:(Swift 和OC的blcok属性不一致问题)