After transitioning a project to ARC, I've been having some issues with delegate methods not being called/being called on deallocated instances. I've realized that the problem is that I have a variable that gets allocated and then executes an asynchronous task. For a simple example, assume that there is an object called MyService that responds to a delegate method, executeDidSucceed:
- (void)fireRequest {
MyService *service = [[MyService alloc] initWithDelegate:self];
[service execute];
}
The original code would look something like this:
- (void)fireRequest {
MyService *service = [[[MyService alloc] initWithDelegate:self] autorelease];
[service execute];
}
With ARC, I understand that a release call gets added after [service execute] gets called. And I also understand that because the method is asynchronous, the service object will get deallocated, and a call to the deallocated object will be made for the delegate method.
I know a solution would be to make service an instance variable and give it the strong property so we can retain ownership of it. And I know of a solution where we could create a block and use a completion handler so the delegate stays retained until the block is completed. My question is, what's the best way of handling a situation like this? Or more so, what's the "best practice" for resolving this while transitioning to ARC?
You will need to make your Myservice object a member to this class. ARC is cleaning it up as soon as this function completes because you no longer have a reference to it.
It's also my opinion that its a good practice to do since you don't have a reference to that object until it calls a delegate (if it does) and depending on the situation you may need stop the service before it completes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With