2016-02-12 11 views
5

Ich versuche, einen Objective-C-Block in Swift 2, um es hinzuzufügen, um ein NSArray wie so zu bauen:Konvertieren Swift 2 Verschluss in Objective-C-Block

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

Ich weiß, es funktioniert einfach gut mit einem Swift-Array, aber ich brauche eine NSArray hier für die Kompatibilität mit bestehenden Objective-C-Code. Und wenn ich ein schnelles Array verwende, weigert sich der Compiler, es auf NSArray zu werfen, weil es kein [AnyObject] (es wird ein [Any] sein wird).

Das Problem hierbei ist, dass eine rasche Schließung ist kein Gegenstand im Gegensatz zu Objective-C-Blöcken, die Objekte hinter den Kulissen sind (sie Instanzen von NSBlock sind, welche eine Unterklasse von NSObject ist)

Also meine Frage ist: Wie erstellt man einen Objective-C Block in swift? Ich habe versucht, @convention (block) in den Typalias zu verwenden, aber es funktioniert nicht.

+1

Duplizieren von http://stackoverflow.com/questions/28211973/swift-closure-as-anyobject oder http://stackoverflow.com/questions/24586293/cast-closures-blocks? –

+0

Danke! Ich habe diese zweite Antwort mit der richtigen Verwendung von 'unsafeBitCast' vermisst. Entschuldigung für das Duplikat ... – deadbeef

Antwort

6

EDIT: Ab Swift 3 ist dies völlig unnötig (und funktioniert nicht einmal). Das Hinzufügen von Closures zu Objective-C-Arrays funktioniert in Swift 3 sofort. Die folgende Antwort gilt nur für Swift 2.

Ich weiß, dass dies ein Duplikat ist, aber ich werde immer noch eine refaktorierte Antwort von swift-closure-as-anyobject und cast-closures-blocks posten, für den Fall, dass jemand zuerst auf diesem landet.

Die Lösung ist, die unsafeBitCast Funktion verwenden, um den Swift-Verschluss zu einem Objective-C Objekt kompatibel zu konvertieren, bevor es zu einem NSArray Hinzufügen und zurück, bevor es in Swift verwenden.

// 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() 
Verwandte Themen