将Swift 2闭包转换为Objective-C块

时间:2016-02-12 12:11:13

标签: objective-c swift2 closures objective-c-blocks

我试图在Swift 2中构建一个Objective-C块,以便将其添加到NSArray,如下所示:

typealias CompletionBlock = () -> Void
let aBlock:CompletionBlock =  {
    print("Hello world!")
}
let nsArray = NSMutableArray()
nsArray.addObject(aBlock) // Error

我知道它可以很好地使用Swift数组,但我需要一个NSArray来与现有的Objective-C代码兼容。如果我使用swift数组,编译器将拒绝将其转换为NSArray,因为它不会成为[AnyObject](它将是[Any])。

这里的问题是swift闭包不是与Objective-C块相反的对象,Objective-C块是场景后面的对象(它们是NSBlock的实例,它是NSObject的子类)

所以我的问题是:如何在swift中创建一个Objective-C块?我尝试在类型中使用@convention (block),但它不起作用。

1 个答案:

答案 0 :(得分:6)

编辑:从Swift 3开始,这完全没必要(甚至不起作用)。向Objective-C数组添加闭包在Swift 3中开箱即用。下面的答案仅适用于Swift 2。

我知道这是重复的,但我仍然会发布swift-closure-as-anyobjectcast-closures-blocks的重构答案,以防有人首先登陆。

解决方案是使用unsafeBitCast函数将Swift闭包转换为Objective-C兼容对象,然后再将其添加到NSArray并在Swift中使用之前返回。

// The `@convention(block)` is important here in order to get
// Objective-C like memory management
typealias CompletionBlock = @convention(block) () -> Void

let aBlock:CompletionBlock = {
    print("Hello world!")
}
let nsArray = NSMutableArray()
let blockObject = unsafeBitCast(aBlock, AnyObject.self)
nsArray.addObject(blockObject)

let closureObject = nsArray[0]
let closure = unsafeBitCast(closureObject, CompletionBlock.self)
closure()