Tuesday, March 20, 2012

Handling delegate callbacks for NSURLConnection

It has been over three years, since I started working with Objective C, primarily for iOS app development. The projects on which I mostly have worked, involve basically a webservice, to which you have to make http GET/POST calls, and display contents in a UITableView.
The UI is mainly prepared within a navigation stack, hence the user can go back & forth between the navigation hierarchy.
The problem here is, though, while a UIViewController is being popped, and a http connection was active, my app crashes with a OBJ_MSG_SEND / EXEC_BAD_ACCESS error.
To cut the long story short, since the delegate for NSURLConnection was not set to nil, the connection tries to deliver a callback to its owner, which in this case has been d'alloced.

The problem?
The catch here is ,though, by studying a few other blog posts, and doing an Instruments research on my own, a NSURLConnection is of the few classes which "retains" its delegate, while however Objective C guidelines state that the delegate should always have "assign" property attribute.
Also, if you go through the documentation of this class, there is no explicit way of setting the delegate to nil!
This means, even if your UIViewController got popped, the http connection is still active, and hence the non-required data will still get transferred, which is not a good practice, for your webservices, and user's network bandwidth as well.

The solution?
Again, going through a few other blog posts, I created my own custom class, "HttpRequest", which is responsible for making network calls, and giving its delegate, the data obtained for the particular http connection.
The modification I made here, is simply added these few lines in HttpRequest.h

BOOL isRequestInProgress;
- (void)cancel;

And the implementation:

- (void)cancel {
if (isRequestInProgress) {
[urlConnection cancel];
[urlConnection release]; urlConnection = nil;
[urlRequets release]; urlRequest = nil;
[mutableData release]; mutableData = nil;
}
}

- (void)makeRequest {
isRequestInProgress = YES;
//make urlconnection.
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
isRequestInProgress = NO;
//your implementation
}
Now in your UIViewController's viewDidUnload method:
[httpRequest cancel];
This will check if at the time of destroying your UIViewController, an active http connection will be cancelled.
Let me know if anyone wants a detailed description of class HttpRequest :-)

No comments:

Post a Comment