关闭

Add closure to extension within swift in runtime

标签: Closureextensionswiftcast-Block
882人阅读 评论(0) 收藏 举报
分类:

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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:49871次
    • 积分:778
    • 等级:
    • 排名:千里之外
    • 原创:28篇
    • 转载:1篇
    • 译文:0篇
    • 评论:5条
    文章分类
    最新评论