Swift 2-UnsafeMutablePointer<Void> al objeto
pointers swift2 (2)
Esto debería funcionar: pase el puntero del objeto como un puntero opaco no administrado a la devolución de llamada:
context.info = UnsafeMutablePointer(Unmanaged.passUnretained(myObject).toOpaque())
SCNetworkReachabilitySetCallback(reachability, callback, &context)
y recuperar en la devolución de llamada a través de:
func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {
let myObject = Unmanaged<MyObject>.fromOpaque(COpaquePointer(info)).takeUnretainedValue()
}
Por supuesto, esto supone que existe una fuerte referencia al objeto siempre que la devolución de llamada esté instalada, de modo que el objeto no se desasigne.
Actualización: Tenga en cuenta que ambas conversiones del puntero de objeto a puntero vacío y viceversa pueden simplificarse si está dispuesto a usar funciones "inseguras":
context.info = unsafeAddressOf(myObject)
// ...
myObject = unsafeBitCast(info, MyObject.self)
El código de ensamblaje generado es, por lo que puedo ver, idéntico.
Actualización 2: Vea también Cómo lanzarse a sí mismo al tipo UnsafeMutablePointer <Void> en swift para obtener más información sobre el "puente" y algunas funciones auxiliares que se pueden usar aquí.
Actualización de Swift 3 (Xcode 8 beta 6):
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
context.info = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
// ...
func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutableRawPointer?) {
if let info = info {
let myObject = Unmanaged<MyObject>.fromOpaque(info).takeUnretainedValue()
// ...
}
}
Si tengo un método como:
func someMethod(contextPtr: UnsafeMutablePointer<Void>)
¿Cómo obtengo el objeto del
contextPtr
?
func someMethod(contextPtr: UnsafeMutablePointer<Void>){
let object:MyObject = contextPtr.memory
}
da:
''Void'' no es convertible a ''MyObject''
¿Cuál es la salsa secreta?
Mas detalle:
Lo que realmente estoy haciendo aquí es configurar una función de devolución de llamada global para
SCNetworkReachability
:
func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {
let r:Reachability = info.memory
}
y luego agregando la devolución de llamada de la siguiente manera:
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
var s = self
withUnsafeMutablePointer(&s) {
context.info = UnsafeMutablePointer($0)
}
SCNetworkReachabilitySetCallback(reachability, callback, &context)
struct S {
var i: Int = 10
}
var first = S()
func foo(contextPtr: UnsafeMutablePointer<Void>){
let pS = UnsafeMutablePointer<S>(contextPtr)
pS.memory.i = 100
}
print(first.i) // 10
foo(&first)
print(first.i) // 100
si necesitamos pasar como UnsafeMutablePointer self to async function
import XCPlayground
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
import Foundation
// can be struct, class ...
class C {
let queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT)
var s: String = ""
func foo() {
var c = self
dispatch_async(queue) { () -> Void in
f(&c)
}
}
}
func f(pV: UnsafeMutablePointer<Void>) {
let pC = UnsafeMutablePointer<C>(pV)
sleep(1)
print(pC.memory.s)
}
var c1: C? = C()
c1!.s = "C1"
c1!.foo() // C1
var c2: C? = C()
c2!.s = "C2"
c2!.foo() // C2
c1 = nil
c2 = nil
print("test")