Correct way to handle various NSURLConnections differently - iphone

I have an iPhone programming making many different NSURLConnections to a server. I use many different webservices, and for each I get a different response.
This means I make many different NSURL connections and I receive many different types of data back.
I have one class handling all my communications. i.e. one class with all the methods to access the webservices.
For every webservice I need to handle the data differently. As of now I have a saperate NSURLConnection delegate wich handles the:
-(void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response;
-(void) connection:(NSURLConnection *) connection didReceiveData:(NSData *) data;
-(void) connection:(NSURLConnection *) connection didFailWithError:(NSError *) error;
-(void) connectionDidFinishLoading:(NSURLConnection *) connection
functions. However, I want something different to be executed depending on the webservice I access.
Do I just need to make a different connection delegate for every webservice I want to handle?
Is there a better way to do this?
Thanks in advance.

You just need to examine the NSURLConnection that is passed into the method. That object corresponds to the connection which the method was tripped from, and you should be able to use that to figure out what web service it came from.

Related

[Why]- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response not invoked

When I use unit-test to request web, the connection:didReceiveResponse is not invoked. However, when I use a button in view to request web , this function can be invoked and it works.The code are really the same, just in different files.
Does anyone know about this?
It is called when enough data has been read to construct an NSURLResponse object.

Handling Broken Download

I have designed an application which will download some data from the server, and all is working fine if there is no network issue. However if there is some network fluctuation during download some data will not be downloaded and the app will crash.
Here I need some help from you guys. Is it possible for me to write a separate code to handle such situation and re-download the entire data by deleting the incomplete downloaded data.
Thank you in advance,
Yes. you can do that.
There are two situation
1. Network not available.
- -> To fix this you have to use "Rechability" sample code(Provided by Apple). Before start downloading you have to check for internet availability.
- ->Or if you are not checking for internet rechability then you will got error code(404) in delegate method of NSURL connection:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
2. Network Fluctuation.
Here I mean in between downloading if network fluctuate. Then it will call below method
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
You can handle all the things inside this method
When there is any network fluctuation or similar problem, you should get a HTTP error code if you are using NSURLConnection or any other network APIs. You could use that to delete the incomplete downloaded data and inform controller code so it could decide if to redownload etc.
Aditya is right. Assume that you are using NSURLConnection If your connection breaks you can read the response code using the following delegate method,
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response {
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
int responseStatusCode = [httpResponse statusCode];
}
and you could proceed with stopping the connection and deleting your unfinished download data.
Updated answer for the comment.
If you are using different connections in different classes you should have this implemented in each of the classes. In my opinion you should have a design like in which a particular class will handle all connection related tasks. (May be it won't suit your requirement). But for your current design you should use this in all your classes.

NSURLConnection: Resume functionality

I'm writing a download manager in Objective-C, and I have it working with resume functionality. I am writing the data to disk as I receive it so that if the download is interrupted for any reason, it should pick up where it left off. Apple says you should expect one or more - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response events. In this event, they say you should reset any data you have previously received because your download is being redirected and the bytes you have already received is invalid, so I delete the existing file and recreate with 0 bytes. But if I receive this event multiple times, I have to delete data I have previously received in the form of a partial download, defeating the purpose of resume functionality. Is there a solution to this?
The solution I have come up with is: only reset the data on- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response events I receive after the first. This would fix the majority of cases (I would think). Is this logically sound? Is there a better alternative? How likely is a file download to fire multiple - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response events?
My recommendation would be to use a library from someone who has already solved this problem, ASIHttpRequest is what I use. It can be found here
Search for 'Resuming' on that page
multipart/x-mixed-replace is used when the server wants to replace what it has already given you with something else. Deleting everything you've downloaded so far is the only sensible option, you can't resume downloading something when the server is telling you to throw it away and use something else instead.
How likely is a file download to fire multiple - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response events?
Extremely unlikely. It's only ever used in certain types of streaming, not for anything you'd need a download manager for.
This is nice and clean library that, I think, has functionality that you need:
https://github.com/Anviking/DownloadManager

Using multiple NSURLConnections at the same time - best practices

In my iPhone app, I've been able to use NSURLConnection properly to download data from a URL. I simply set the delegate to my UIView, and make sure that I set up the UIView to answer for the proper delegate functions such as -connection:didReceiveResponse:. However, if I have a number of NSURLConnections (either for a similar type of request, or multiple kinds of requests), it gets messy because the delegate functions, such as didReceiveRequest, don't differentiate between the different requests. The advantage of asynchronous requests is that you are supposed to be able to multiple at once, without blocking the main thread. What's the best practice for how to use multiple NSURLConnection requests at the same time?
I prefer to wrap them in a higher-level object (like ImageDownloader or SomeWebServiceCall) that has all the per-connection/call state information. I usually create a delegate these objects so that the caller gets a more specific callback when the operation has succeeded or failed.
Perhaps look into ASIHTTPRequest, instead of NSURLConnection. ASIHTTPRequest makes a lot of this work trivially easy.
In this case, I'd say NSOperation is your best bet. ASIHTTPRequest is based on NSOperation and allows you to handle each request as an operation, which serves as the delegate for its own NSURLConnection.
You'll have to be careful here though, because by default NSOperations are run on separate threads, but some APIs, like this one, are required to be executed on the main thread. If you inspect the source code to ASIHTTPRequest you'll notice they've got some infrastructure to ensure delegate methods are called on the main thread.
Create an instance variable for each NSURLConnection and NSMutableData. All of your delegate methods have the NSURLConnection object as an argument, so you can match them as such:
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (connection == aConnection) {
// Do something with the data for aConnection
} else if (connection == otherConnection) {
// Do something with the data for otherConnection
}
}
This still limits you to one connection per instance variable, so it's not suitable for, for instance, a table view with images on each row that need to be loaded.

iPhone SDK : Asynchronous Connection Retry Mechanism

I have implemented the usual Asynchronous connection mode in one of my apps and it works fine. The error handling is also happening properly. I also have implemented the Reachability API by Apple.
I would like to have for example 5 retires to be done when there is a network failure.
Kindly suggest me a good way to implement this.
Implementing the retry option was simple actually.
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
Use this method to make sure you identify the error condition while a try is failed. You can reinitiate the request again inside this method with a int flag has the NO_MAX_RETRY(eg.5) set.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection this method when returned the connection is successful and you can reset the retry flag and release the retry routine.