2009-06-08 43 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例程中清除很多。

相關問題