Add closure to extension within swift in runtime

来源:互联网 发布:微博怎么绑定域名 编辑:程序博客网 时间:2024/05/21 12:08

Add closure to extension within swift

主要是利用objc_setAssociatedObject将closure添加到实例中去,先看看该方法在Objective-cswift中的声明:

Objective-C

void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)

swift:

public func objc_setAssociatedObject(object: AnyObject!, _ key: UnsafePointer<Void>, _ value: AnyObject!, _ policy: objc_AssociationPolicy)

主要是参数value的类型,分别是idAnyObject,在Objective-C中,系统会自动将Block转化id类型,正常使用,而在swift里则会提示形如下面的错误信息:
实例代码:

typealias TestClosureType = ()->()var testClosure: TestClosureTypeobjc_setAssociatedObject(self, "Test Block", testClosure, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

错误信息提示如下:

Cannot convert value of type 'TestClosureType' (aka '()->()') to expected argument type 'AnyObject!'

原因很清晰,类型不符合,只需要将closure转成AnyObject类型即可,借助于:

public func unsafeBitCast<T, U>(x: T, _: U.Type) -> U

可以将 closure转成AnyObject类型,只是我们还需要修改点东西,修改之后的结果如下:

typealias TestClosureType = @convention(block)()->()var testClosure: TestClosureTypeobjc_setAssociatedObject(self, "Test Block", unsafeBitCast(testClosure, AnyObject.self), .OBJC_ASSOCIATION_RETAIN_NONATOMIC)

取出来的时候再转回去,方法如下:

let completionBlock = unsafeBitCast(objc_getAssociatedObject(self, "Test Block"), TestClosureType.self)

使用这个方法,主要是想偷懒,当然定义代理啊通知啊等等都可以解决问题,另当别论。

参考:Cast Closures/Blocks

1 0
原创粉丝点击