How do I extend the duration of delegate objects for the duration of the delegate callback?

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 { // Assume "worker" is a retain property to a Worker // instance that we previously created and began working, // and that it also the sender of the message. self.worker = nil; // Other code... } 

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?

+6
source share
2 answers

I think the burden lies with the Worker in this example. The problem that I see is that the Worker object does something internally after it tells its Consumer that its work is completed. The worker exists only for the consumer, therefore, if the consumerโ€™s goal is met, why does the worker continue to do what is of no value to the consumer? If there are internal tasks that need to be performed after completing the "consumable" work, then these tasks will not be properly placed in the Worker object instance, but probably this should be done by another internal object belonging to the less volatile library class, which will not be canceled by actions Consumer.

+1
source

When a delegate receives a notification, he should start observing the employee and release him only when the someFinushed method is completed.

0
source

All Articles