Swift 2 – UnsafeMutablePointer <Void>为对象

如果我有一个方法,如:

func someMethod(contextPtr: UnsafeMutablePointer<Void>) 

如何从contextPtr获取对象?

 func someMethod(contextPtr: UnsafeMutablePointer<Void>){ let object:MyObject = contextPtr.memory } 

得到:

“虚空”不能转换为“MyObject”

秘诀是什么?


更多详情:

我在这里实际做的是为SCNetworkReachability设置一个全局callback函数:

 func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) { let r:Reachability = info.memory } 

然后添加callback,如下所示:

 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) 

这应该工作:将对象指针作为一个不透明的非托pipe指针传递给callback:

 context.info = UnsafeMutablePointer(Unmanaged.passUnretained(myObject).toOpaque()) SCNetworkReachabilitySetCallback(reachability, callback, &context) 

并通过以下方式检索callback:

 func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) { let myObject = Unmanaged<MyObject>.fromOpaque(COpaquePointer(info)).takeUnretainedValue() } 

当然,这假定只要callback被安装,就存在对该对象的强引用,以便该对象不被释放。

更新:请注意,如果您愿意使用“不安全”函数,则可以简化从对象指针到void指针的返回以及返回。

 context.info = unsafeAddressOf(myObject) // ... myObject = unsafeBitCast(info, MyObject.self) 

生成的汇编代码 – 就我所见 – 完全相同。

更新2:另请参见如何将self转换为unsafeMutablePointer <Void>在swift中键入有关“桥接”的更多信息以及可在此处使用的一些帮助函数。


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() // ... } } 
 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 

如果我们需要将UnsafeMutablePointer自身传递给asynchronous函数

 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")