Swift C回调 - takeUnretainedValue或takeRetainedValue用于Swift类指针

时间:2017-06-23 11:16:15

标签: ios swift memory-management

我有几个UIViewUITableViewCell。在里面我有C回调,例如:

CCallback(bridge(self),
       {(observer, data) -> Void in
          let mySelf = Unmanaged<DetailedView>.fromOpaque(observer!).takeRetainedValue()
           mySelf.fillLoadedData(data: data)
        });

其他地方

func bridge<T : AnyObject>(_ obj : T) -> UnsafeMutableRawPointer {
    return UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
}

在C:

void CCalback(void * classPtr, void(*callback)(void *, MyData)){
   //fill data
   callback(classPtr, data)
}

我应该在关闭时使用takeUnretainedValuetakeRetainedValue吗?据我了解,保留将增加对象引用计数,因此它不会被自动销毁?否则,如果我使用takeUnretainedValue,如果self被自动释放,则会崩溃,因此使用takeRetainedValue会阻止它。我对么?

1 个答案:

答案 0 :(得分:2)

对象指针可以转换为Unsafe(Mutable)RawPointer(Swift 等价或不保留对象的C void *

let ptr = UnsafeMutableRawPointer(Unmanaged.passUnretained(obj).toOpaque())
// Does not retain `obj`

let ptr = UnsafeMutableRawPointer(Unmanaged.passRetained(obj).toOpaque())
// Retains `obj`

转换回对象指针(通常在回调中完成) 从C)调用的函数可以使用或不使用retain:

let obj = Unmanaged<T>.fromOpaque(ptr).takeUnretainedValue()
// Does not consume a retain

let obj = Unmanaged<T>.fromOpaque(ptr).takeRetainedValue()
// Consumes a retain

如果回调处于活动状态,obj的生命周期保证 那么最简单的方法就是使用&#34;未获取的&#34;两个方向的转换。你有责任保留obj 回调是有效的,例如通过在obj之前取消注册回调 被取消初始化。

另一种方法是使用passRetained()obj转换为 一个指针。这样就可以保留物体,从而使物体保持活力#34; 回调仍然可以使用&#34;未返回的&#34;转换为转换 指向对象指针的指针,不会减少保留计数。 但是必须有一个takeRetainedValue()调用来消费 保留。之后,如果没有,则可以销毁该对象 其他参考文献。

更一般地说,每次拨打passRetained(obj)都会增加保留 计数和每次调用takeRetainedValue()会减少它,因此它们必须正确平衡。