Swift 2 - UnsafeMutablePointer<Void> 对象
Swift 2 - UnsafeMutablePointer<Void> to object
如果我有这样的方法:
func someMethod(contextPtr: UnsafeMutablePointer<Void>)
如何从 contextPtr
中获取对象?
func someMethod(contextPtr: UnsafeMutablePointer<Void>){
let object:MyObject = contextPtr.memory
}
给出:
'Void' is not convertible to 'MyObject'
秘诀是什么
更多详情:
我在这里实际做的是为 SCNetworkReachability
:
设置一个全局回调函数
func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {
let r:Reachability = info.memory
}
然后添加回调如下:
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
var s = self
withUnsafeMutablePointer(&s) {
context.info = UnsafeMutablePointer([=15=])
}
SCNetworkReachabilitySetCallback(reachability, callback, &context)
这应该有效:将对象指针作为不透明的非托管指针传递
到回调:
context.info = UnsafeMutablePointer(Unmanaged.passUnretained(myObject).toOpaque())
SCNetworkReachabilitySetCallback(reachability, callback, &context)
并通过以下方式在回调中检索:
func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {
let myObject = Unmanaged<MyObject>.fromOpaque(COpaquePointer(info)).takeUnretainedValue()
}
当然,这假设存在一些对该对象的强引用
只要设置了回调,这样对象就不会
释放。
更新: 注意,从对象指针到void指针的两种转换
如果您愿意使用 "unsafe" 函数,则可以简化返回:
context.info = unsafeAddressOf(myObject)
// ...
myObject = unsafeBitCast(info, MyObject.self)
据我所知,生成的汇编代码是相同的。
更新 2: 另请参阅 了解更多信息
关于 "bridging" 和一些可以在这里使用的辅助函数。
Swift 3 更新(Xcode 8 测试版 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 传递给异步函数
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")
如果我有这样的方法:
func someMethod(contextPtr: UnsafeMutablePointer<Void>)
如何从 contextPtr
中获取对象?
func someMethod(contextPtr: UnsafeMutablePointer<Void>){
let object:MyObject = contextPtr.memory
}
给出:
'Void' is not convertible to 'MyObject'
秘诀是什么
更多详情:
我在这里实际做的是为 SCNetworkReachability
:
func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {
let r:Reachability = info.memory
}
然后添加回调如下:
var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
var s = self
withUnsafeMutablePointer(&s) {
context.info = UnsafeMutablePointer([=15=])
}
SCNetworkReachabilitySetCallback(reachability, callback, &context)
这应该有效:将对象指针作为不透明的非托管指针传递 到回调:
context.info = UnsafeMutablePointer(Unmanaged.passUnretained(myObject).toOpaque())
SCNetworkReachabilitySetCallback(reachability, callback, &context)
并通过以下方式在回调中检索:
func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {
let myObject = Unmanaged<MyObject>.fromOpaque(COpaquePointer(info)).takeUnretainedValue()
}
当然,这假设存在一些对该对象的强引用 只要设置了回调,这样对象就不会 释放。
更新: 注意,从对象指针到void指针的两种转换 如果您愿意使用 "unsafe" 函数,则可以简化返回:
context.info = unsafeAddressOf(myObject)
// ...
myObject = unsafeBitCast(info, MyObject.self)
据我所知,生成的汇编代码是相同的。
更新 2: 另请参阅
Swift 3 更新(Xcode 8 测试版 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 传递给异步函数
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")