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:
-(void)createDelegate
{
self.delegating = [Delegating new]; // I create and hold the instance strongly
delegating.delegate = self; // I customize it
}
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 have self
as the delegate, you should do the whole installation process in one method:
-(void)installService
{
self.handler = [[XXHandler alloc] init]; // Hold the handler strongly
self.service = [[YYService alloc] initWithDelegate:handler];
}
If you do not know the concrete instance object acting as delegate, pass it as argument:
-(void)installServiceWithDelegate:(id)delegate
{
self.delegate = delegate;
self.service = [[YYService alloc] initWithDelegate:delegate];
}
…
[self installServiceWithDelegate:[YourConcreteClass new]];
But you should not try to turn things upside down or inside out.