1

我试图找出围绕调用委托回调的内存管理的最佳实践。我过去看到的一个问题是,调用委托回调可能会导致对象在返回之前被释放,如果对象在调用回调后尝试访问自己的属性,这可能会导致对象崩溃。

例如,一个对象(例如A)可能会做这样的事情:

- (void)doStuff
{
    [_delegate done];
    NSLog(@"msg = %@", _msg);
}

如果调用done导致A被释放,则随后的访问尝试_msg将导致 BAD_ACCESS 崩溃。

可以通过延迟调用done直到下一个运行循环(例如通过执行 a dispatch_async)来解决这个问题,但这将迫使我们不得不使其异步。或者,我们可以self在调用之前保留done并在之后立即释放,但这似乎也是一个 hacky 解决方法。有没有人推荐处理这个问题的风格?

4

3 回答 3

0

它崩溃是因为您要调用的委托引用了一个已释放的对象。要修复此崩溃,您需要Delegate = nil;在您的 dealloc 方法中进行设置。您不能设置委托的属性,retain因为它会导致内存管理问题。

于 2013-12-31T10:34:10.397 回答
0

老实说,我不确定这个问题是否真的与“代表”有关,但总的来说更多的是内存管理。

如果您没有完成一个对象,请确保您仍然“保留”它。当你完成它“释放”它并且不要进一步访问它。

如果可能的话,也尝试搬到 ARC,生活会变得更轻松!:)

于 2013-05-14T08:45:45.900 回答
-2

委托方法不应该释放发送者。是什么让你在这种情况下奔跑?

总是可以在一个 (C) 块中将 +1 与 -1 方法配对。

如果您使用 MRC:无论如何,我更喜欢在委托方法中的发送者上保留 + 自动释放,然后再通过委托中的保留 + 释放导致释放。因此,应该像往常一样将发送者作为参数添加到委托方法中:

- (void)senderIsDone:(Sender*)sender
{
   [[sender retain] autorelease];
…
   [sender release]; // Something like this in your code
}

但根本不应该:这不应该发生。

另一种策略是延迟导致释放的代码。在上面的例子中

- (void)senderIsDone:(Sender*)sender
{
    [sender performSelectorOnMainThread:@selector( release ) withObject:nil waitUntilDone:NO]; // Whatever make the sender disappear
}
于 2013-05-14T08:17:07.463 回答