简体   繁体   中英

What's the equivalent of '[[something retain] autorelease]' in ARC?

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:

  1. Add a method to your class which simply sets theDbRequest to nil , let's call this cleanUpTheDbRequest .
  2. Change your delegate callback to invoke [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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM