views:

104

answers:

4

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?

+1  A: 

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?

kubi
Yes, ARequest is basically a class that creates an NSURLConnection to asynchronously submit a request.I could use an ivar, but I may have a few requests being sent at once, so I'd then have to maintain a collection of requests of some sort. Apple seems to use a pattern that doesn't require the maintenance of this sort (SKProductsRequest for example) however.
Tricky
A: 

I once did the same thing as you. I wrote a Category-Method on NSString to send it it to a server, that will print it. In the Category-Method I had to call [self retain], so that the callback methods could be a NSString-Categroy-Method to.
I felt so bad about it, that I rewrote everything to use a Singleton, that is accessed by the Category-Method. So the Singleton will retain the string as long as necessary.

vikingosegundo
Yes, that's the thing... It does feel 'bad' for some reason, but I wonder if it really is? Apple manages this somehow in SKProductsRequest for instance, but is it via a [self retain] or do they maintain a collection of outstanding requests somewhere?
Tricky
+1  A: 

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.

Dave DeLong
+2  A: 

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.)

Ahruman