Add closure to extension within swift in runtime

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: TestClosureType
objc_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: TestClosureType
objc_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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值