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

7

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

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

我知道使用Swift数组可以正常工作,但为了与现有的Objective-C代码兼容,我需要一个NSArray。如果我使用Swift数组,编译器会拒绝将其转换为NSArray,因为它不是[AnyObject](它是[Any])。
问题在于Swift闭包不是对象,而Objective-C块是对象(它们是NSObject子类NSBlock的实例)。所以我的问题是:如何在Swift中创建Objective-C块?我已经尝试在类型别名中使用@convention(block),但它不起作用。

1
重复的问题,参见 https://dev59.com/m14c5IYBdhLWcg3wMnz1 或 https://dev59.com/LGAf5IYBdhLWcg3wey3Z? - Martin R
谢谢!我错过了那个正确使用unsafeBitCast的第二个答案。对于重复问题感到抱歉... - deadbeef
1个回答

7

编辑:从Swift 3开始,这完全是不必要的(甚至不起作用)。在Swift 3中,将闭包添加到Objective-C数组可以直接使用。下面的答案仅适用于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()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接