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

Convert Swift 2 closure to Objective-C block

我正在尝试在 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 块相反的对象,后者是幕后的对象(它们是 NSBlock 的实例,是 NSBlock 的子类NSObject)

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

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

我知道这是重复的,但我仍然会 post 来自 and cast-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()