einen Objektzeiger (dh eine Instanz eines Referenztyp) kann mit einem UnsafePointer<Void>
umgewandelt (dem Swift-Mapping von const void *
, UnsafeRawPointer
in Swift 3) und zurück. In Objective-C würden Sie
void *voidPtr = (__bridge void*)self;
//
MyType *mySelf = (__bridge MyType *)voidPtr;
(Siehe 3.2.4 Bridged casts in der Clang ARC-Dokumentation für die genaue Bedeutung dieser Würfe.) Schreiben
Swift hat einen Unmanaged
Typ für diesen Zweck. Es ist ein wenig umständlich zu verwenden, weil es mit COpaquePointer
statt UnsafePointer<Void>
arbeitet. Hier sind zwei Hilfsmethoden (benannt nach der Objective-C __bridge
cast):
func bridge<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
return UnsafePointer(Unmanaged.passUnretained(obj).toOpaque())
// return unsafeAddressOf(obj) // ***
}
func bridge<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
return Unmanaged<T>.fromOpaque(COpaquePointer(ptr)).takeUnretainedValue()
// return unsafeBitCast(ptr, T.self) // ***
}
Der „kompliziert“ Ausdruck ist nur dann notwendig Swifts strenges Typsystem zu erfüllen. In dem kompilierten Code ist dies nur eine Besetzung zwischen Zeigern. (Es kann kürzer geschrieben werden, wie in den ***
Kommentaren angezeigt , wenn Sie bereit sind, „unsicher“ Methoden zu verwenden, aber die kompilierte Code ist identisch.)
Mit Hilfe dieser Hilfsmethoden Sie self
auf eine C-Funktion übergeben können
let voidPtr = bridge(self)
(UnsafeMutablePointer<Void>(bridge(self))
oder wenn die C-Funktion ein veränderlicher Zeiger erfordert ), und wandelt es zurück auf einen Objektzeiger - zB in einer Callback-Funktion - als
let mySelf : MyType = bridge(voidPtr)
Keine Übertragung des Eigentums erfolgt, so dass Sie self
existieren, solange der void-Zeiger verwendet wird, muss sicherstellen.
Und der Vollständigkeit halber, würde der Swift-Äquivalent von __bridge_retained
und __bridge_transfer
von Objective-C
sein
func bridgeRetained<T : AnyObject>(obj : T) -> UnsafePointer<Void> {
return UnsafePointer(Unmanaged.passRetained(obj).toOpaque())
}
func bridgeTransfer<T : AnyObject>(ptr : UnsafePointer<Void>) -> T {
return Unmanaged<T>.fromOpaque(COpaquePointer(ptr)).takeRetainedValue()
}
bridgeRetained()
das Objekt Zeiger auf einen void-Zeiger wirft und behält das Objekt. bridgeTransfer()
konvertiert den Void-Zeiger zurück in einen Objektzeiger und verwendet den Retain-Wert.
Ein Vorteil ist, dass das Objekt zwischen den -Aufrufen nicht freigegeben werden kann, da eine starke Referenz gehalten wird. Der Nachteil ist, dass die Anrufe müssen richtig ausbalanciert sein, und dass es leicht dazu führen kann, behalten Zyklen.
Update für Swift 3 (Xcode 8):
func bridge<T : AnyObject>(obj : T) -> UnsafeRawPointer {
return UnsafeRawPointer(Unmanaged.passUnretained(obj).toOpaque())
}
func bridge<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
}
func bridgeRetained<T : AnyObject>(obj : T) -> UnsafeRawPointer {
return UnsafeRawPointer(Unmanaged.passRetained(obj).toOpaque())
}
func bridgeTransfer<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()
}
Die entsprechenden Änderungen an "unsicheren pointers" sind in
Wie weisen Sie self zu inputProcRefCon zu? Ich hoffe, Sie haben dies durch- https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html – Shripada
Ein anderes Beispiel: http://stackoverflow.com/questions/33260808/swift- ordnungsgemäße-Nutzung-von-cfnotificationcentererdobserver-w-callback/33262376 # 33262376. –
Eigentlich @MartinR Ich denke deine Antwort hier ist hilfreicher: http://StackOverflow.com/a/30788165/341994 – matt