views:

1085

answers:

4

Hi, When passing a delegate to the a NSUrlConnection object like so:

[[NSURLConnection alloc] initWithRequest:request delegate:handler];

when should you call release on the delegate? Should it be in connectionDidFinishLoading? If so, I keep getting exec_bad_access. I'm seeing that my delegates are leaking through instruments.

Thanks

+1  A: 

It will depend on what object handler is and how you use it. For example, I usually use self as my delegate:

[[NSURLConnection alloc] initWithRequest:request delegate:self];

I don't need to call release on self because delegates are not retained and self will be released by another object.

If handler is a new object, then you will have to release it (and connectionDidFinishLoading: should be ok, unless you need to use the handler object for something else).

Are you familiar with the rules for memory management in Cocoa?

Can you give a better picture of what object handler is and how you're using it?

hjon
A: 

Your need to release the connection, not the delegate. The NSURLConnection class I think does not retain the delegate, which is why you get a crash when you try and release it.

The two places to release the delegate are connection:DidFinishLoading, and connection:didFailWithError.

Kendall Helmstetter Gelner
yeah, that's what I thought too, but when I do that... I get the exec bad access gods smiting me.
Kieran H
Actually, I'm pretty sure NSURLConnection does retain the delegate (it's an exception in this regard).
eman
NSURLConnection does indeed retain the delegate, check the documentation.
Julio Gorgé
A: 

the object handler is used to implement connectionDidFinishLoading didReceiveData etc. I make a lot of calls to a number of web services and instead of creating one object for each, I have a central class for all that stuff:

@interface DataService : NSObject {} 

- (void) search:(NSString *) name byAddress:(NSString *)address; 

@end

so the implementation of that method creates the delegate to pass:

SearchDelegate *delegate = [[SearchDelegate alloc] init]; 
[self sendRequestToUrl:urlString withJson:jsonString andHandler:delegate];

what I am seeing in Instruments is that there is a memory leak on the SearchDelegate... so I think it is actually being retain'ed.

Tinkering a bit I changed my sendRequestToUrlMethod to have this:

// http code setup blah...

[[NSURLConnection alloc] initWithRequest:request delegate:handler];
[handler release];

and this seems to have gotten ridden of memory leak being reported in Instruments.

Kieran H
+1  A: 

Be careful with NSURLConnection initWithRequest, it does in fact retain the delegate, though I don't know why that would be useful. Don't belive me, just add this assert around the create steps as see for yourself.

int retainCountIn = self.retainCount;

// Create NSURLConnection, passing self as the delegate

int retainCountOut = self.retainCount; NSAssert(retainCountIn == retainCountOut, @"retainCount incremented on delegate");

The only really safe thing to do is create another little object that will act as the delegate, your class can then hold a ref to it and the connection can hold a ref to it via the delegate. Then, when you are done with the connection (after say a cancel), you can release your ref and the connection can release its ref whenever, and all is well. This is the safe way to avoid a circular ref issue that would otherwise be very hard to figure out and debug.

cheers Mo DeJong

MoDJ