Swift 2 - UnsafeMutablePointer <Void>到对象

Ash*_*lls 22 pointers swift swift2

如果我有一个像这样的方法:

func someMethod(contextPtr: UnsafeMutablePointer<Void>)
Run Code Online (Sandbox Code Playgroud)

我如何从中获取对象contextPtr

func someMethod(contextPtr: UnsafeMutablePointer<Void>){    
    let object:MyObject = contextPtr.memory
}
Run Code Online (Sandbox Code Playgroud)

得到:

'Void'不能转换为'MyObject'

什么是秘诀


更多详情:

我在这里做的是设置一个全局回调函数SCNetworkReachability:

func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {

    let r:Reachability = info.memory
}
Run Code Online (Sandbox Code Playgroud)

然后添加回调如下:

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)
Run Code Online (Sandbox Code Playgroud)

Mar*_*n R 41

这应该工作:将对象指针作为不透明的非托管指针传递给回调:

context.info = UnsafeMutablePointer(Unmanaged.passUnretained(myObject).toOpaque())
SCNetworkReachabilitySetCallback(reachability, callback, &context) 
Run Code Online (Sandbox Code Playgroud)

并通过以下方式检索回调:

func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {

    let myObject = Unmanaged<MyObject>.fromOpaque(COpaquePointer(info)).takeUnretainedValue()

}
Run Code Online (Sandbox Code Playgroud)

当然,假设只要安装了回调,就会存在对该对象的强引用,因此不会释放该对象.

更新:请注意,如果您愿意使用"不安全"函数,则可以简化从对象指针到void指针和返回的两次转换:

context.info = unsafeAddressOf(myObject)
// ...
myObject = unsafeBitCast(info, MyObject.self)
Run Code Online (Sandbox Code Playgroud)

生成的汇编代码 - 据我所知 - 相同.

更新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()
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 好的解决方案 不过,我很惊讶我花了多长时间才发现这一点.鉴于某些低级API对不安全指针的依赖,你会认为很多人都需要知道这一点! (3认同)