我正在开发一个Swift项目,该项目使用包装在C ++中的C库。
该库为您提供了同步和异步获取/设置变量的可能性。
作为回调方法的库,用于通知何时甚至发生。
我很快拥有此功能:
/*** Convert const void* To Any T ***/
func bridgeToTypeRetained<T : AnyObject>(ptr : UnsafeMutableRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()
}
func bridgeToTypeUnretained<T : AnyObject>(ptr : UnsafeRawPointer) -> T {
return Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
}
和
/*** Convert const void* To Any T ***/
func bridgeToPointerRetained<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Unmanaged.passRetained(obj).toOpaque())
}
func bridgeToPointerUnretained<T : AnyObject>(obj : T) -> UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
}
对于从库中实现回调,在库中,我具有以下定义:
DllExport void STDCALL CpProxyAvOpenhomeOrgInfo1SetPropertyTrackCountChanged(THandle aHandle, OhNetCallback aCallback, void* aPtr);
typedef void (STDCALL *OhNetCallback)(void* aPtr);
然后我迅速使用以下代码:
CpProxyAvOpenhomeOrgInfo1SetPropertyTrackCountChanged(myHandle, { (pointer) in
if pointer != nil{
let myClass:MyClass = bridgeToTypeRetained(ptr: pointer!)
myClass.aValu = 0 //CRASH BAD ACCESS
let myClass:MyClass = bridgeToTypeUnretained(ptr: pointer!)
myClass.aValu = 0 //NO CRASH
}
}, bridgeToPointerRetained(obj: self))
对于实现异步操作,在库中有以下定义:
DllExport void STDCALL CpProxyAvOpenhomeOrgInfo1BeginCounters(THandle aHandle, OhNetCallbackAsync aCallback, void* aPtr);
typedef void (STDCALL *OhNetCallbackAsync)(void* aPtr, OhNetHandleAsync aAsync);
然后迅速使用以下代码
let classCallback = ClassCallback()
classCallback.classObject = self
CpProxyAvOpenhomeOrgInfo1BeginCounters(prxHandleId, { (pointer, ohNetAsync) in
if pointer != nil && ohNetAsync != nil{
let classCallback : ClassCallback = bridgeToTypeRetained(ptr: pointer!)
classCallback.classObject.aValue = 1 //NO CRASH
}
}, bridgeToPointerRetained(obj: classCallback))
所以我的问题是:
谢谢。
答案 0 :(得分:1)
如果您希望ClassCallback
存在,即使您所有对它的Swift引用都消失了,也需要传递一个保留值,这会导致内存泄漏而没有添加适当的清除逻辑。一个未保留的值,那么当您尝试取回ClassCallback
时,如果所有快速引用都消失了,则会崩溃。
在您的回调中,您可以采用一个未保留的引用来获取该对象,前提是您希望该对象以作用域结尾处的当前引用计数继续存在。如果您使用保留的引用,则引用计数将减少并破坏该对象(如果这是最后一个引用)。
我通常要做的是传递保留的引用,并获取未保留的引用,直到准备好处理回调对象为止。发生这种情况时,我将使用上下文指针的保留值(在您的情况下为aPtr
)来平衡保留的传递并将其替换为新的适当值。