I have two classes, ClassA that will instantiate ClassB and pass off a method as a delegate. ClassB will eventually invoke ClassA’s delegate. Do I need to add a retain on ClassA when ClassB stores it?
I’m following the “Implementing a Delegate for a Custom Class” from the “Cocoa Fundamentals Guide: Communicating with Objects” but the sample code demonstrated doesn’t seem to take memory management into account.
ClassA will set the delegate and expect to be called back later when ClassB is done with it’s work.
@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");
}
Header file for the ClassB that’ll store and then later invoke the delegate:
@interface ClassB
id targetObject;
SEL targetMethod;
-(void) setCallback:(id)anObject withSelector:(SEL)aMethod
ClassB’s implementation:
@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];
}
}
You wouldn’t retain ClassA in ClassB, because ClassA already owns ClassB and it’s assumed that when ClassA is deallocated, it will take care of cleaning up any references in ClassB.
If you followed the “normal” rules of ownership and retained ClassA when setting the delegate method in ClassB, you’d end up with a retain loop where neither objects would ever be deallocated. Instead, you should be using a weak reference exactly like you are.