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
Taken from my blog post here: http://i.ndigo.com.br/2012/01/releasing-nsurlconnection-and-its-delegate/
You will have to pay extra attention to the delegate object as, for NSURLConnection
, there is a special consideration for the delegate: it is always retained.
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/doc/uid/20001697-BAJDDIDG
initWithRequest:delegate:
Special Considerations: The connection retains delegate. It releases delegate when the connection finishes loading, fails, or is canceled.
So, taking that into consideration, you have several options to ensure that your delegate will be released correctly and I will try to explain 2 simple ones.
The first, and most commonly used, is to use the same class that initialize the NSURLConnection as the delegate.
[[NSURLConnection alloc] initWithRequest:request self];
By doing that, your class the retain count would be increased by 1 when the connection starts and then would de reduced by 1 after the connection finishes loading, fails, or is canceled, resulting in no memory leaks.
The second option, the one that you are trying to do, is to use another object to handle all connection calls. This works fine as well, but you will need extra attention with memory. One simple thing you could do to solve your problem is to initialize the connection with an autorelease object.
//creates the handler object
MyHandlerClass *handler = [[MyHandlerClass alloc] init];
//creates the connection with handler as an autorelease object
[[NSURLConnection alloc] initWithRequest:request delegate:[handler autorelease]];
OR you could release your handler right after creating the connection (as it will be already retained by the connection)
//creates the handler object
MyHandlerClass *handler = [[MyHandlerClass alloc] init];
//creates the connection with handler
[[NSURLConnection alloc] initWithRequest:request delegate:handler];
//releases handler object
[handler release];
Both ways will leave the handler object ownership only with the connection class, which will release the handler object right after it finishes loading, fails, or is canceled, once again resulting in no memory leaks.
EDIT: By doing any of the options above you don't have to worry about releasing the delegate (but you still have to release the connection) in connection:DidFinishLoading
and connection:didFailWithError
methods.
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?
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