Convert Swift 2 closures to Objective-C block

I am trying to build an Objective-C block in Swift 2 to add it to NSArray , for example:

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

I know this will work just fine with a Swift array, but I need NSArray here for compatibility with existing Objective-C code. And if I use a fast array, the compiler will refuse to give it to NSArray because it will not be [AnyObject] (it will be [Any] ).

The problem is that quick closure is not the opposite of Objective-C blocks, which are objects behind the scene (they are instances of NSBlock , which is a subclass of NSObject )

So my question is: how to create an Objective-C block in swift? I tried using @convention (block) in typealias but it does not work.

+5
source share
1 answer

EDIT: As of Swift 3, this is completely unnecessary (and not even working). Adding closures to Objective-C arrays works out of the box in Swift 3. The answer below is only valid for Swift 2.

I know this is a duplicate, but I will still post the refactored answer swift-closure-as-anyobject and cast-closures-blocks in case someone lands on this first.

The solution is to use the unsafeBitCast function to convert the Swift closure to an Objective-C compatible object before adding it to NSArray and back before using it in 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() 
+6
source

Source: https://habr.com/ru/post/1242866/


All Articles