对象指针(即引用类型的实例)可以转换为(在 Swift 3 中UnsafePointer<Void>
的 Swift 映射)并返回。在 Objective-C 中你会写const void *
UnsafeRawPointer
void *voidPtr = (__bridge void*)self;
//
MyType *mySelf = (__bridge MyType *)voidPtr;
(有关这些转换的确切含义,请参阅 Clang ARC 文档中的3.2.4 桥接转换。)
Swift 有一个Unmanaged
用于此目的的类型。使用起来有点麻烦,因为它与COpaquePointer
而不是UnsafePointer<Void>
. 这里有两个辅助方法(以 Objective-C 转换命名__bridge
):
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) // ***
}
“复杂”的表达式只需要满足 Swift 的严格类型系统。在编译的代码中,这只是指针之间的转换。***
(如果您愿意使用“不安全”的方法,它可以写得更短,如注释中所示,但编译后的代码是相同的。)
使用此辅助方法,您可以传递self
给 C 函数
let voidPtr = bridge(self)
(或者UnsafeMutablePointer<Void>(bridge(self))
如果 C 函数需要一个可变指针),并将其转换回对象指针 - 例如在回调函数中 - 如
let mySelf : MyType = bridge(voidPtr)
不会发生所有权转移,因此self
只要使用 void 指针,您就必须确保它存在。
为了完整起见,Objective-C 的 Swift 等价物__bridge_retained
将__bridge_transfer
是
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()
将对象指针转换为 void 指针并保留该对象。bridgeTransfer()
将 void 指针转换回对象指针并使用保留。
一个优点是不能在调用之间释放对象,因为持有强引用。缺点是调用必须适当平衡,并且很容易导致保留循环。
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()
}
对“不安全指针”的相关更改在