I have an object that is set as the delegate of another object, whose delegate
property is weak.
- (YYService *)service
{
XXHandler *handler = [[XXHandler alloc] init];
// YYService's "delegate" property is weak
return [[YYService alloc] initWithDelegate:handler];
// The XXHandler is deallocated because there are no strong references to it
}
Since nothing else references the delegate it ends up getting deallocated, but I want it to live for as long as the parent object does as if the parent had a strong reference to its delegate. Is there a simple way to accomplish this?
The easy why to "solve" that problem is to subclass
YYService
, giving the subclass an additional strong property and set that one in-initWithDelegate:
.But this "solution" would deepen a problem in your design instead of solving that.
Let's have a look, why delegates are usually hold weakly:
The delegating class has a general – or no – behavior which might not fit in the class' user's case, i. e. if something happens. (An operation completes, an error occurs, $whatever) So the delegating class gives you the opportunity to customize the behavior including running custom code. Delegating is in competition with subclassing, but in difference to subclassing is on a per instance basis (instead of a per class basis) and at run time (instead of compile time).
Because it works on per instance basis, the instance creating the delegate typically holds the delegating instance strongly. This code knows the customization that should apply to the delegating instance:
Then the delegating instance cannot hold the delegate strongly, because this would be a retain cycle.
In your snippet that does not work, because
-service
returns the newly created delegating instance. And even it would be possible to return both instances, I wouldn't like it, because creating the delegating object and installing the delegate would be a two-step operation, even it is semantically a one-stepper. So If you do not haveself
as the delegate, you should do the whole installation process in one method:If you do not know the concrete instance object acting as delegate, pass it as argument:
But you should not try to turn things upside down or inside out.