views:

35

answers:

1

In objective-c you are responsible for releasing objects you allocate, but what happens when you allocate an object in a method, assign self as the objects delegate, and then release the object.

The callbacks from the newly created (and released) object fails at this point, or rather, doesn't happen.

- (void)doSomething
{
    MyObj *myObj = [[MyObj alloc] init];
    myObj.delegate = self;
    [myObj performOperation];
    [myObj release];
}

- (void)callbackMethodFromMyObj:(NSString *)message
{
    NSLog(message);
}

EDIT: To extend this a bit more, perhaps it's essential to include that MyObj is using NSURLConnection.

MyObj:

@implementation MyObj

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [self.delegate callbackMethodFromMyObj:@"a string"];
}

I can't release the object until the callback has occurred, and I can't avoid releasing the object in the same method that creates it (because it exists outside the scope).

One way of doing it would be to pass the object along in the call-back and release it in the callback, but is this the right way to go about this?

I have updated this post to include the fact that I'm using NSURLConnection, so threading is involved here.

If I were to release *myObj then it would be released before NSURLConnection has a chance to call - (void)connectionDidFinishLoading:(NSURLConnection *)connection

As I see it, and from the reply below, it seems like it's essential to pass *myObj along as a parameter in the callback, thus releasing it inside - (void)callbackMethodFromMyObj:(NSString *)message

and changing the method signature, resulting in the following method:

- (void)callbackMethodFromMyObj:(NSString *)message withMyObj:(MyObj *)sender
{
    // do things
    [myObj release];
}
A: 

Edit

If you are the author of the MyObj class, more specifically if you are controlling the method that invokes the callbackMethodFromMyObj: callback then you could treat MyObj as a short-lived one-time operation object that releases itself after it invokes its callback, i.e.

/* We are inside MyObj, some internal method */
NSString* message; // Assuming

[self.delegate callbackMethodFromMyObj: message];
[self release]; // add this

This way you do not leak specific logic concerning the lifetime of your MyObj instances into delegates. Even better, since delegates are always optional (well, they should be!), even if you do not supply a delegate the MyObj will be correctly garbage collected.

Hope this helped.

Original answer

Your example is a bit confusing but if I understand it correctly, you wish to create some kind of Command object (say MyObj being NSInvocation) and perform some kind of delegate notification with the instance that creates it (e.g. self).

If what you do in performOperation is occurring in the same thread as doSomething then you have nothing to fear because the callback will be called before the release message even gets dispatched.

What's confusing is that you mention...

...what happens when you allocate an object in a method, assign self as the objects delegate, and then release the object.

If you allocate an object and then release it without assigning it somewhere else first (e.g. a retaining property) then it will get immediately deallocated. It doesn't exist anymore and nothing references it to dispatch the performOperation message, thus the delegate is redundant.

If you wish to hold on to the object, assign it to a retaining property.

To make the delegate more portable, I'd advise, as you've already mentioned yourself, you to pass the delegatee (in your case MyObj) into the callback.

Denis 'Alpheus' Čahuk
This is an interesting approach, however, what if the callback method is never called?Imagine that the NSURLConnection never calls - (void)connectionDidFinishLoading:(NSURLConnection *)connectionThen the release would never happen, and memory would leak.
That is the responsibility of the MyObj class, not the delegate - which is what the context of this question covers. If you've created the MyObj class, then it is the implementor's job to make sure he covered all states a NSURLConnection can end up in, including any other dependencies you might be using. Do mind the Single Responsibility Principle while you're doing this. If MyObj becomes too complex, you might want to look into refactoring it.
Denis 'Alpheus' Čahuk
Good point, but isn't this causing MyObj to be responsible for releasing it self?I thought the idea was that what ever created an instance of an object, was responsible for releasing it (unless it's an autoreleased instance).Saying that MyObj should release it self, seems to stray from this.