I am going to translate a very common situation into a general form. Let's say I create some kind of library object that disconnects, does some asynchronous work, and then calls the delegate method when it is done. Now let's also say for some arbitrary reason that I cannot use ARC or blocks for a callback. This is old fashioned. Let me call this object Worker.
Now say that in different applications there are several other classes that do not know anything about Work, except for their public interface. They use the workers for their own purposes. Let me call these classes Consumers.
Say Worker delegates delegates as follows:
// "Private" method called internally when work is done. - (void)somethingFinished { [self.delegate workerDidFinish]; [self someTask]; }
And let's say a particular consumer handles the callback as follows:
- (void)workerDidFinish {
Now, if nothing else has preserved this particular instance of Worker, we have a problem. The worker will be freed, then the control will revert to its -someTask method, after which it will send -someTask to the fixed or garbage memory and probably fail. No one violated the rules of memory management.
I am not asking for a technical solution here. I know a few options. I wonder who the responsibility for the correction lies. Should I, as a component developer, implement the Worker -somethingFinished method so that the Workerโs [[self retain] autorelease] throughout the method with something like [[self retain] autorelease] at the beginning? Or should I, when the component consumer needs to know, that I could deflate the object halfway through the instance method and wait until it releases it?
This question answers everyone, seems to indicate that releasing an object from a callback is a bad idea. Unfortunately, this question has a lot of distracting information about exactly how the worker (CLLocationManager in this instance) is passed to the delegate, which I deliberately avoided here. This question has the same scenario and offers a different solution.
Personally, I do not see how the consumer can be held responsible. It does not violate memory management rules and politely consumes the open Worker interface. It just frees up the instance when it is no longer needed. But, on the other hand, does this mean that any object that can somehow be freed from the middle method must artificially extend its own life? After all, delegate methods are not the only way that a sender can be freed up in the middle of a method.
So ultimately, who is responsible for the correction? Working? Consumer? Is it possible to define canonically?