16

我正在使用 Box2D (C++),我创建了一个 Objective-C 对象并将其分配给 Box2D 主体的userData属性,该属性的类型为void*.

现在在某些情况下,void* userData可能是对该 ObjC 对象的唯一活动引用。因此,因为我(__bridge void*)在作业中使用了ARC,所以放手了。这是我需要解决的问题。

我一直在思考防止这种情况发生的选项?我阅读了Clang 的 ARC 文档,特别是关于桥梁铸造的部分(以及关于 SO 的问答)以及对他们认为“格式错误”的各种桥梁铸造结构点头。

不过,我的第一个想法是(__bridge_retained void*)在对 userData 的初始分配中使用。但这让我想知道如何平衡保留?我显然不能向对象发送释放。

那么我必须要CFRelease()对象吗?还是需要CFBridgingRelease()?还是在这里都是非法的?

(__bridge_transfer void*)userData临时 id 类型转换是否足够,可能在之后将 userData 设置为 NULL 时?这甚至是个好主意吗?

我知道另一种方法是为对象保留一个单独的NSArray/并使它们与 Box2D 主体的生命周期保持同步,与它们的 Box2D 主体同步添加和删除它们。NSDictionaryuserData

但这感觉有点矫枉过正,因为在这里我知道我在做什么,我知道+1只要 Box2D 主体处于活动状态,我就需要该对象,而-1当 Box2D 主体被移除时,我需要该对象。另外,我知道只有两种方法可以添加和删除 Box2D 主体,并且userData在我的框架中甚至无法直接访问,因为所有 Box2D 对象都隐藏在 Objective-C 接口/包装器后面。

暂时将可能“格式不正确”放在一边,您建议我在这种情况下应该做什么?

4

2 回答 2

25

__bridge_retained意思是“通过保留此 ARC 对象将其发送到无 ARC 区域”。当您需要创建“未跟踪”时,您可以调用它void *。所以,在你的情况下,userData = (__bridge_retained void *)obj.

__bridge_transfer意思是“通过释放它把这个物体从无弧的土地上拉回来”。当您想要有效地使void *. 所以,obj = (__bridge_transfer id)userData。在此之后,userData指针就不能安全使用了;相反,您只使用obj. 当obj超出范围时,ARC 将最后一次释放它。id这可能需要专门为此目的创建一个临时文件。

因此,在您的情况下,您确实希望在__bridge_retained将对象运送到 Box2D 时使用,并__bridge_transfer在您想要使userData. 如果您需要userData作为 Objective-C 对象访问但不使指针无效,请使用 plain __bridge

于 2013-02-08T22:38:21.770 回答
2

您误解了文档作者对“格式错误”的含义。这是格式错误的:

NSData* data; // Initialized
NSData* data2= (__bridge NSData*) data;

这也是格式不正确的:

void* data; // Initialized
void* data2= (__bridge void*) data;

这不是格式错误的:

NSData* data; // Initialized
void* data2= (__bridge void*) data;

不病态就足够了,左值是可保留的,右值是不可保留的,反之亦然。因此,由于在您的情况下您将对象指针转换为原始指针,反之亦然,您的方法是正确的。

在您的位置,我将实现一个智能指针,该指针在构造时发送 CFBridgingRetain 消息,在销毁时发送 CFBridgingRelease 消息。

于 2013-02-08T23:04:25.817 回答