2009-06-08 40 views
2

我有两个类,ClassA将实例化ClassB并将方法作为委托传递。 ClassB最终将调用ClassA的委托。 ClassB存储它时,是否需要在ClassA上添加保留?在ObjectiveC中实现自定义类的代理时引用计数

我按照“Cocoa基础指南:与对象通信”中的“为自定义类实现委托”,但示例代码演示似乎没有考虑到内存管理。

ClassA将设置委托,并期望在ClassB完成它的工作后再被调用。为ClassB的

@implementation ClassA 

-(void)launchSomething 
{ 
    ClassB *classB = [[ClassB alloc] init]; 
    [classB setCallback:self withSelector:@selector(deferredWork)]; 

    // do some other stuff, assign class B to some View and eventually release class B 
} 

-(void)deferredWork 
{ 
    NSLog(@"this is the method that will be deferred till some point in time"); 
} 

头文件会保存,再后来调用委托:

@interface ClassB 

id targetObject; 
SEL targetMethod; 

-(void) setCallback:(id)anObject withSelector:(SEL)aMethod 

ClassB的的实现:

@implementation ClassB 
-(void) setCallback:(id)anObject withSelector:(SEL)aMethod 
{ 
    // QUESTION: Do I need to add a 'retain' here on the targetObject? 
    targetObject = anObject; 
    targetMethod = aMethod; 
} 

-(void) someWorkLater 
{ 
    if ([targetObject respondsToSelector:@selector(targetMethod)]) { 
     // invoke the target object with the specific method 
     [targetObject targetMethod]; 
    } 
} 

回答

2

在ClassB的你不会保留ClassA的,因为ClassA已经拥有ClassB,并且假定当ClassA被释放时,它将负责清理ClassB中的任何引用。

如果您在ClassB中设置委托方法时遵循了“常规”所有权规则并保留了ClassA,那么最终会得到一个保留循环,其中任何对象都不会被释放。相反,你应该像你一样使用一个弱引用。

0

正如马克所说,可可的正常做法是让代表们成为“弱”链接。也就是说,他们不被保留。由委托人来确保当它不再能够作为delagate进行响应时,不会发生任何不良事件 - 通过将委托设置为零或释放源对象(假设它是唯一所有者并且它将立即释放) 。

所以在你的例子中,如果classB在launchSomething结束后仍然存在,那么你大概已经将它存储在ivar中。对于CLASSA你的dealloc例行要么必须

[classB setCallback:nil]; // optionally withSelector:@selector(none) 

和/或

[classB release]; 

如果CLASSB可能拥有的任何其他业主,那么你绝对应该使用setCallback:无,但往往你知道你是唯一所有者。

当涉及到视图和窗口时,事情会变得复杂,因为它可能很难确保订单对象被释放,并且没有其他人与classB有强大的联系,在这种情况下,清除回调是至关重要的。

这同样适用于观察者和通知,这些观察者和通知通常是弱链接,在你的dealloc例程中清除很多。

相关问题