What's the equivalent of [[something retain] autorelease]
in ARC?
I have a problem where a class DBRequest calls my delegate to signify completion. My delegate then sets the DBRequest instance to nil, which dealloc's it. But then when the stack pops out of my delegate and jumps back to the DBRequest, it of course then crashes.
If I wasn't in ARC, in my delegate I'd simply do [[theDbRequest retain] autorelease]
before releasing my reference to it, so that it'd survive long enough until the next run loop autoreleased it.
What should I do in ARC?
How about adding something like
__strong DBRequest * myself = self;
[delegate reportDone];
I think that'll increment the self object until the end of the function preventing it from dying early.
My delegate then sets the DBRequest instance to nil, which dealloc's it. But then when the stack pops out of my delegate and jumps back to the DBRequest, it of course then crashes.
Surely this was always a bad strategy, and your [[theDbRequest retain] autorelease]
was always just covering up the problem, yes?
Simply do nothing. So your instance variable sticks around; so what? You know that ARC will release it for you when you are dealloced.
The important thing is not to release theDbRequest
, but to set theDbRequest's reference to you (the delegate) to nil, so it doesn't try to call you back when you no longer exist. Your own dealloc would be a good place to do that.
Hope I'm understanding the issue correctly. If not, post some code!
As @matt says if you simply do nothing ARC should clean up when your object is deallocated - assigning the DBRequest
you create to an instance variable handles that (provided of course your object outlasts the object you are creating).
If you need to deallocate the DBRequest
before your object dies then you need an ARC-compatible "trick" equivalent to [[theDbRequest retain] autorelease]
. Now unless you are constructing your own auto release pools your previous approach would trigger at the end of the current event. Following that logic try:
theDbRequest
to nil
, let's call this cleanUpTheDbRequest
.[self performSelectorOnMainThread:@selector(cleanUpTheDbRequest) withObject:nil waitUntilDone:NO]
instead of directly assigning nil
to theDbRequest
This should delay the assigning of nil
till after the end of the current event, just as your autorelease "trick" did. It also works if your DBRequest
lives across multiple events - the previous method kicks in at the end of the event the autorelease
is called in, this method at the end of the event the delegate method is called in.
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