您的位置:首页 > 移动开发 > Swift

Add closure to extension within swift in runtime

2015-11-19 22:44 591 查看

Add closure to extension within swift

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

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
的类型,分别是
id
AnyObject
,在
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息