忽略'对象发送 - 自动发送太多次'警告

时间:2011-08-06 04:53:51

标签: iphone

运行Analyzer时,我收到“Object sent -autorelease too times”警告。我知道我正在做一些棘手的事情(我愿意接受完成目标的替代方案)。

基本上,我想保留一堆特定类型的控制器,以方便从中心位置发送消息。所以,考虑一下:

来自'ActionBroker'共享对象:

NSMutableSet *liveActions;
liveActions = [NSMutableSet alloc] init];

...

CLViewController *action = [[[actionClass alloc] init] autorelease];
if (!action) {
    return nil;
}    
[self.liveActions addObject: action];
// When adding an object, the retain count is increased. We want the action
// to dealloc, so that it might remove itself from the list...
[action release];
return action;    

补充的dealloc代码:

[[CLActionBroker sharedActionBroker] removeAction: self];        
[super dealloc];

...并在removeAction:

[action retain];
[self.liveActions removeObject:action];

上面的代码有效,我只是得到了唠叨的错误。我可以用不同的方式解决问题的唠叨感。

此代码的一个用例是通过一系列打开的控制器传递'handleOpenURL'请求并返回第一个'YES'响应。

2 个答案:

答案 0 :(得分:3)

据我了解,您的意图是在集合中设置一组控制器(“操作”),您可以从应用程序的任何位置轻松访问。如果其中一个控制器被释放,它将自动从集合中删除。

但是这个设置存在问题。正如您在上面所描述的那样,控制器应该在取消分配时从liveActions集中删除。但是,由于NSSet保留其成员,只要它仍在liveActions集中,您的控制器永远不会被解除分配。 -dealloc仅在所有保留已由发布平衡时运行。

这会导致您的过度释放,从而导致警告。由于您已发送了额外版本,因此当控制器仍在-dealloc集中时,{/ 1}} 可以运行。但是当你从那个集合中删除它时,它会向你的对象发送一个liveActions消息,这将使其保留计数为负数。这可能是安全的,也可能不安全,但在任何一种情况下,这都是一个丑陋的解决方法。

你真正想要的是一套不保留其成员的集合。这通常是危险的配置,因为它可能导致集合中的悬空指针。但是如果你愿意管理对象的生命周期并在适当的时候清除那些悬空指针,那么事实证明这是非常可行的。您只需使用release而不是CFMutableSet。由于这两者是免费的桥接,它甚至没有增加那么多的复杂性。

设置NSMutableSet如下所示:

CFMutableSet

之后,您可以像使用任何其他// The NULL for the third parameter tells the set to not do anything when // an object is added to or removed from the set. CFMutableSetRef cfLiveActions = CFSetCreateMutable(NULL, 0, NULL); // Toll-free bridging makes this possible NSMutableSet *liveActions = (NSMutableSet *)cfLiveActions; 一样使用它;这个将是特别的,因为它不会保留其成员。

答案 1 :(得分:1)

问题:

CLViewController *action = [[[actionClass alloc] init] autorelease]; // +0 ownership
// ...
[self.liveActions addObject: action]; // liveActions takes ownership
// ...
[action release]; // -1 ownership

当您alloc编辑对象时,您应对此负责。但是当你autorelease它时,你已经履行了你的义务(因为你自动释放而不是释放,你仍然可以使用该对象直到下一轮的runloop)。你以后不应再release

此外:

[action retain];
[self.liveActions removeObject:action];

保留是不必要的。

(这是另一个开始切换到ARC的插件,根据该插件你不必担心这个!)

[编辑:误解了你的问题。即将修订的答案。] [编辑2:没关系......即使我误解了你的意图,我相信我的解决方案仍然正确。]