关于委托的问题

9

这段代码非常简单,但是是否正确呢?我不确定是否需要保留通过init方法传递的委托。

@interface SomeClass : NSObject {
    SomeClassDelegate *someClassDelegate;
}
-(id)initWithDelegate:(SomeClassDelegate *)delegate;
@end

@implementation SomeClass
-(id)initWithDelegate:(SomeClassDelegate *)delegate
{
    [delegate retain]; // should I be doing this?
    someClassDelegate = delegate;
}
-(void)dealloc
{
    [delegate release]; // obviously only do  this if I DO need to retain it
    [super dealloc];
}
@end

我的初步想法是否定的,然而这段代码似乎暗示了另一种情况。我知道我不能依赖retain counts,但我想知道处理委托的正确方法。

// self's retain count is 1
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:req delegate:self];
// the retain count is now 2, did the init of URLConnection retain self?

1
NSURLConnection 是一个特殊情况。它不仅保留委托,而且在连接期间一直保留它,因为停止接收委托消息的唯一方法是取消连接。也就是说,通常不会保留委托,并且 NSURLConnection 的行为像这样是实现细节;不应该依赖或通常模仿。此外,拥有委托类是不寻常的。通常声明委托协议。 - Mike Abdullah
谢谢,Mike。这解释了我看到的问题。 - Jab
2个回答

11
一般情况下,你不应该保留代理(delegate)。因为代理已经持有你的对象(object)的引用,如果你保留代理,就会创建一个循环引用(circular reference)。同样地,由于这个原因,你可以假设在代理销毁之前,你的对象已经被销毁了。
查看这些文章以获取更多关于使用/实现代理的信息:这些 文章
编辑:有一些例外情况,已经被其他人指出。

感谢这些文章,您证实了我对委托的信念。Mike在我的问题评论中也向我解释了为什么我看到了NSURLConnection的情况。 - Jab
2
根据情况,您的对象可能不会首先被销毁,但至少它的委托将被取消。(例如:UIAccelerometer) - rpetrich

1
正如htw所说,通常情况下您不应该保留委托。在多线程环境中,您经常需要保留所有需要的内容,即使只是为了方法调用的持续时间,以确保它不会在背后被无效化。例如(实际上并非如此),如果-[NSURLConnection initWithRequest:delegate]创建了一个新线程,那么该线程可能已经保留了(然后很可能会自动释放)其参数。实际上,NSURLConnection是一个特殊情况,它会在连接期间保留其委托。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接