Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bad-practice to retain 'self'?

I have a simple query that I'd like cleared up by someone... Is it bad-practice to retain self?

I have a server request object that I'd like to make. I'd like to be able to use it in the following fashion:

ARequest *request = [ARequest request: someParam];
request.delegate = self;
[request begin];

In order for the object not to self destruct as soon as the autorelease pool is drained, I imagine I need to call a retain in it's init method and then a release once the server response has been received, processed and delivered to it's delegate.

However, something is raising a warning bell in my head with this approach. Better ways to do it?

like image 527
Tricky Avatar asked Oct 17 '10 13:10

Tricky


3 Answers

There is nothing wrong with retaining self, as long as you release it at some well-defined point in accordance with normal memory management protocol. If an object requires itself to exist until some condition is met, it should take responsibility for that, in the same way as it does for any other object it requires to continue existing.

Introducing otherwise extraneous manager objects or foisting the responsibility off on the object’s owner for superstitious reasons would be the real anti-pattern here.

(The equivalent approach in garbage-collected code would be for the object to exclude itself from garbage collection while results are pending, or root it through a collection of some sort if you dislike that idea.)

like image 117
Jens Ayton Avatar answered Oct 08 '22 00:10

Jens Ayton


It's not unheard-of, but it is somewhat uncommon. The main way I've seen it used (and used it myself) is when you're dealing with some sort of semi-synchronous object (by semi-synchronous I mean that it does not block the main thread, but it also does not execute on a background thread; an NSURLConnection would fit this bill). For example, I wrote a subclass of NSWindowController that was specifically for displaying a window as a sheet and for invoking some certain delegate callbacks. Basically, you'd alloc/init a new sheet controller and invoke beginSheetForWindow:. This would run the sheet semi-synchronously, and then invoke an appropriate callback when the sheet was dismissed.

Since the invoking object doesn't necessarily "own" the sheet (think of it as a Mac version of a modal view controller on iOS), the sheet controller does [self retain] immediately before showing the sheet, and [self release] immediately after cleaning up and invoking callbacks. The purpose behind this was to ensure that the controller object would stick around until the sheet was done. (The sheet, IIRC, was retained by the runloop, but I also needed the controller to stick around)

Like I said, it's very rare to come across a situation where you would want to [self retain], but it's not impossible. However, as a general rule of thumb, if you think that you need to [self retain], you may want to think again.

like image 28
Dave DeLong Avatar answered Oct 08 '22 01:10

Dave DeLong


Easiest way to do this would be to create an iVar for your request, retain the request when you start it and release it when the last delegate method is called.

Is ARequest a class you created? Does it create a new thread to asynchronously submit the request?

like image 25
kubi Avatar answered Oct 08 '22 02:10

kubi