AXUIElementRef和ARC - 取消分配的实例和__bridge与__bridge_transfer

时间:2013-03-13 10:24:42

标签: objective-c cocoa nsmutablearray dealloc memory-management

我在NSMutableArray上收到此错误:

  -[Not A Type release]: message sent to deallocated instance 0x1006e29c0

它发生在这一行:

     [_array removeAllObjects];

现在,我理解错误意味着什么,但不知道为什么会发生这种情况。

我在上面的行之前添加了一个NSLog,如下所示:

      NSLog(@"%@", [_array class]);

这正常执行并且行为正确,这是日志:

 2013-03-13 11:19:27.366 App[66921:303] __NSArrayM
 2013-03-13 11:19:27.367 App[66921:303] *** -[Not A Type release]: message sent to deallocated instance 0x1006e29c0

所以在删除它之前似乎没有被解除分配..

即使我删除removeAllObjects调用并用下面的行替换它,我仍然会得到同样的错误。

     _array = [[NSMutableArray alloc] init];

我在代码中的其他地方所做的就是调用[_array addObject:...]

_array是一个强大的财产:

@property (strong) NSMutableArray *array;

首先在init方法中初始化数组。

编辑:我正在将AXUIElementRefs添加到此数组中,如下所示:

 [_array addObject:(__bridge_transfer id)elementRef];

我认为__bridge_transfer将它带到了ARC,我不需要管理其中任何一个?

可能是什么问题?

更新: 以下是一个示例项目:http://users.telenet.be/prullen/AXMemory.zip

这是一个有效的项目,因为我正在使用__bridge而不是__bridge_transfer。

这个项目包含一个简单的循环,它一遍又一遍地做同样的事情。这是为了证明只有__bridge,AXUIElementRefs永远不会被释放。他们留在记忆中。这也是我在仪器分析器中看到的。您还可以通过活动监视器查看内存使用量每几秒钟增加一次。

AXUIElementRefs是通过AXUIElementCopyMultipleAttributeValues获得的 - 所以我会假设我拥有它们的所有权?然而,更改为__bridge_transfer会导致上述错误。

如果有人可以看看这个并让我知道我做错了什么,那将非常感激。

我通过以下语句获得了一系列属性:(第60行)。

         AXUIElementCopyMultipleAttributeValues(frontWindowRef, attributes,0,&attributeValues);

第110行我分配AXUIElement(循环子数组):

             element = CFArrayGetValueAtIndex(childrenArrayRef, i);

第112行是我将AXUIElementRef添加到数组的地方:

             [_array addObject:(__bridge id)(element)];

第36行是我清空它的地方,如果超过500个元素:

if ([_array count] > 500) {
    [_array removeAllObjects];
}

1 个答案:

答案 0 :(得分:3)

你不能只假设__bridge_transfer将它带到ARC并[你]不需要管理任何这些“。你必须了解你当时对elementRef有哪些权利和责任(我们无法从你所写的内容中得知)。

如果您使用相应的CFBridgingRetain()CFBridgingRelease()函数,我发现理解桥接强制转换要容易得多。 __bridge_transferCFBridgingRelease()相同。所以,问题是:你当时拥有elementRef吗?你发布它是否合适?

考虑一下,以下是否正确?

[_array addObject:(__bridge id)elementRef];
CFRelease(elementRef);

如果没有,那么__bridge_transfer也不是。

从您收到的错误的性质来看,我强烈怀疑您无权释放elementRef,因此您无权告诉ARC它拥有它并且必须将其释放。您已导致AXUIElementRef过度释放。您应该使用__bridge强制转换 - 不使用“转移”而不使用CF…Release()