Have buttons override other processes - objective-c

In my app, the root view controller acquires information from the internet, parses it, and displays it in viewDidAppear. I am using this method because my app in embedded in a UINavigationController and this way the root view controller will reload its data when the user presses the back button and pops to the root view.
When this occurs, it takes some time for the information from the internet to be acquired and displayed. During this time, if the user clicks a button to move to a different view, the button action will not occur until the view controller has completed its process of acquiring the web data.
How can I make it so that the buttons will override the other processes and immediately switch the view? Is this safe? Thanks in advance.
Edit
Here's an example of a portion where I take the information off of the site (My app parses the HTML).
NSURL *siteURL = [NSURL URLWithString:#"http://www.ridgefield.org/ajax/dist/emergency-announcements"];
NSError *error;
NSString *source = [NSString stringWithContentsOfURL:siteURL
encoding:NSUTF8StringEncoding
error:&error];

This is where Apple folks would hound, "don't block the main thread!".
The primary suggestion for this kind of workflow is to use a separate thread (read: queue) for loading data from the web. Then the worker who completes the load can set some property on your view controller, and inside that setter is where the UI should be updated. Remember to call the setter back on the main thread.
There are several ways to skin the concurrency cat, but the answer to this particular question leaves them out of scope. The short answer is to not do the load in the main thread, and that should lead you to the right place.

The NSString method stringWithContentsOfURL is synchronous and will block your main thread.
Instead of using background threads to solve the problem, you can use asynchronous URL requests. This does not block the user interface because a delegate protocol is used to let you know when the request is complete. For example:
NSURL *url = [NSURL URLWithString:#""http://www.ridgefield.org/ajax/dist/emergency-announcements""];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLConnection* theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
And then some of your delegate methods are:
-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)theResponse
{
// create received data array
_receivedData = [[NSMutableData alloc] init];
}
-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)theData
{
// append to received data.
[_receivedData appendData:theData];
}
-(void)connectionDidFinishLoading:(NSURLConnection*)connection
{
// now the connection is complete
NSString* strResult = [[NSString alloc] initWithData: _receivedData encoding:NSUTF8StringEncoding];
// now parse strResult
}

Related

How can I pause the program until nsurlconnection complete?

I know that people have asked this but I have not found satisfactory answers. I have one method that I send all my URLRequests through. I return the response of the request as a string when the method completes. I have recently added ssl to my program. This means that I can no longer use a synchronous request because I need to take advantage of the didReceiveAuthenticationChallenge function as my credentials are currently self-signing. The program needs the response from the URL in order to continue so there is not harm in waiting for the response. However, I cannot seem to find a way to just hold the code up and continue once completed. I can alert the original function that called to request function but I would like the program to pick up right after that call. And it has unique code below such calls so I cannot specialize the connectionDidFinishLoading: function because each method who calls this is different.
How can I pause the program so I can return the nsdata from the connection to the methods that called it?
Here is some pseudo-code to show you what I mean:
- (void) login:(NSString *)username :(NSString *)password {
NSString *str = [NSString stringWithFormat:%#"%#:::%#",username,password];
NSURL *url = [NSURL urlWithString:#"https://blahblahblah"];
NSString *result = [self connectToUrl:str:url];
if ([result isEqualToString:#"valid"]) {
//this would be more complex in here
NSLog(#"hooray");
} else {
NSLog(#"bummer");
}
}
- (NSString *)connectToUrl:(NSURL *)url :(NSString *)str {
NSData *FileData = [str dataUsingEncoding: NSUTF8StringEncoding];
NSMutableData *data = [[NSMutableData alloc] initWithCapacity:100];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"POST"];
//set up the rest of the request...
...
connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];
//WOULD LIKE TO PAUSE HERE UNTIL COMPLETE! THEN CONTINUE
// received data is assigned in didReceiveData: method
return [[[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding] autorelease];
}
But alas, I cannot do this because I cannot make the final line wait until the connection is complete... Please help me!
Very appreciative!
R
iOS and OS X and much of the Cocoa/Cocoa touch frameworks are built on an event model. You don't pause your app. That's not the proper approach. You need to start the connection and then move on. When the connection completes, you act on that event.
In other words, your login method can't sit and wait for the result. It should start the connection and return.
When you get the result of the connection you call some method to process the login result.
Making use of blocks can make things like this easier but there are other ways. You just need to stop thinking about such things in a linear fashion. Dealing with asynchronous processing requires a different approach.

NSURLConnection delegate

REVISED...
The crux of the app is communicating with a database server. Responses from the server to the app are all in XML. There are several screens. Example, screen 1 lists the user's information, screen 2 lists the user's past trades, allows new trades, and so on.
Here is some code from my AppDelegate:
StartViewController *svc = [[StartViewController alloc] init];
TradeViewController *tvc = [[TradeViewController alloc] init];
CashViewController *cvc = [[CashViewController alloc] init];
ComViewController *covc = [[ComViewController alloc] init];
PrefsViewController *pvc = [[PrefsViewController alloc] init];
NSMutableArray *tabBarViewControllers = [[NSMutableArray alloc] initWithCapacity:5];
UITabBarController *tabBarController = [[UITabBarController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:svc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;
navigationController = [[UINavigationController alloc] initWithRootViewController:tvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;
navigationController = [[UINavigationController alloc] initWithRootViewController:cvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;
navigationController = [[UINavigationController alloc] initWithRootViewController:covc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;
navigationController = [[UINavigationController alloc] initWithRootViewController:pvc];
[tabBarViewControllers addObject:navigationController];
navigationController = nil;
[tabBarController setViewControllers:tabBarViewControllers];
[[self window] setRootViewController:tabBarController];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
Trying to stick with the MVC style, I have a singleton class which does all of the "processing".
Now an example on how I run into a wall… the user can change their email address on screen 5. Enter new email address into text field and click the save button. The button then calls a method from the singleton class which sends the new email address to the server and (via the URL) and receives a XML response confirming the change.
Here are my problems:
1. I start the spinner from the view controller before I make the singleton class method call - but not knowing when the app to server send/receive is finished, how do I make the spinner stop at the right time? I can't of it from the singleton class, I tried that. From what I know, it has to be from within the VC or is there a way to change VC output from my singleton class?
The singleton class NSURLConnection is handling ALL of my communication. Everything from a simple, email change all the way to updating transaction tables. This just seems wrong to me and makes it very difficult to keep track on who is calling what. Again, I am going by my interpretation of MVC. I think it would be much easier to have a NSURLConnection for every VC and do some processing in those classes. However that would not be MVC(ish).
I have close to a 100 variables, arrays, etc… in my singleton class which I use to assign values to all my VC. This also seems wrong to me but I can't think of any other way.
how can I distinguish in the NSURLConnection delegate
(connectionDidFinishLoading) which URL call is being made?
Each of the delegate methods (such as -connectionDidFinishLoading:) has a connection parameter that tells you which connection sent the message. A given connection can only load one URL at a time, so there's a one to one correspondence between URLs and connections.
How can I tell outside of "connectionDidFinishLoading" when the download is completed?
That method tells you when the connection is finished. It's up to you to store that information somewhere where it's useful to your app.
Update: Based on what you've added, your "processing" class is your app's model. The rest of the app shouldn't care that each transaction involves a message to the server -- that's the model's business alone. Also, there's no reason that the model has to be a single object (let alone a singleton) -- it can be a group of objects that work together.
So, you might have a class (let's call it Processor) that represents the application's interface to the model (some might even call this a "model controller"). An instance of Processor might create a local database for storing the current local state of the app.You might also have a Transaction class that represents a single transaction with the server. A transaction could create a request, send it to the server, get the response, update the database, and tell the Processor that the transaction is done. Or, maybe when some other part of the app (like one of your view controllers) asks the Processor to process a new transaction, the Processor passes the requesting object along to the transaction that it creates so that the transaction can update the requestor directly.
It's hard to say what the best plan for your app is without knowing where you're planning on taking it, but the usual guidelines hold:
break your problem into parts that are easier to solve
limit the scope of each class's responsibilities
if something seems to complicated, it probably is
Breaking your model up into several classes will make it easier to test, as well. You can imagine how easy it would be to write a set of unit tests for the Transaction class. The same goes for Processor -- if the server transaction stuff is in a different class, it's easier to test that the Processor is doing the right thing.
If you have multiple NSURLConnections for the same delegate, consider using a global (well, let's say rather an instance variable) NSMutableDictionary instance, in which you store the data depending on which NSURLConnection is being called. You can use, for example, the in-memory address of the connections converted to an NSString (something like
[NSString stringWithFormat:#"%p", connection]
should do the trick).
Also, in the connectionDidFinishLoading: and connection:didFailLoadWithError: methods, remove the keys corresponding to the NSURLConnections. Thus, you can tell it from 'outside' if a connection is finished: just check if it is in the dictionary or not.
If you're downloading any data over a network connection, I would suggest using ASIHttpRequest. This will allow you to download files asynchronously, meaning your interface doesn't freeze during the download process.
If you use ASIHttpRequest, you can also set the didFinishSelector. By doing this, you can control which method is called when a specific URL has finished loading.
Have a look at this:
NSURL *url = [NSURL URLWithString:#"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
[request setDidFinishSelector:#selector(requestDone:)];
Then:
- (void)requestDone:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
// If you want, you can get the url of the request like this
NSURL *url = [request url];
}
As for the second part of your question, if the requestDone: method has not been called, you know the download has not completed.
If you want to do something more complicated with multiple downloads, ASIHttpRequest offers queue functionality too. Take a look here.
Hope this will help you.
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
{
NSString *urlString = [[[connection originalRequest] URL] absoluteString];
if ([urlString caseInsensitiveCompare:#"http://www.apple.com"] == NSOrderedSame) {
//Do Task#1
}
else if ([urlString caseInsensitiveCompare:#"http://www.google.com"] == NSOrderedSame)
{
//Do Task#2
}
}
I would recommend subclassing NSURLConnection. Simply add two properties: an NSInteger, tag, and a BOOL, isFinished. This way, you can #define tags for each different request and then identify them by tag in your delegate methods. In connectionDidFinishLoading, you can set the isFinished BOOL to YES, and then you can check in other methods if then connection is finished.
Here's my own NSURLConnection subclass, TTURLConnection:
TTURLConnection.h:
#import <Foundation/Foundation.h>
#interface TTURLConnection : NSURLConnection <NSURLConnectionDelegate>
#property (nonatomic) NSInteger tag;
#property (nonatomic) BOOL isLocked;
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:
(BOOL)startImmediately tag:(NSInteger)tagParam;
#end
TTURLConnection.m:
#import "TTURLConnection.h"
#implementation TTURLConnection
#synthesize tag;
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:
(BOOL)startImmediately tag:(NSInteger)tagParam {
self = [super initWithRequest:request delegate:delegate
startImmediately:startImmediately];
if(self) {
self.tag = tagParam;
}
return self;
}
#end

Why does NSURLConnection timeout when sending many requests?

I am writing a network class for an iOS app. This class will take care of all logging and network traffic. I have a problem where I have to send possibly thousands of requests at one time, but NSURLConnections are timing out because the delegate methods will not be called until all the NSURLConnections are started, by which time the timeout period has expired. I am using a rest API for Drupal and, unfortunately, I do not know of a way to create multiple instances with one request. How can I receive responses while simultaneously sending them? If I use GCD to pass off the creation of the NSURLConnections, will that solve the problem? I think I would have to pass the entire operation of iterating over the objects to send and sending to GCD to free up the main thread to answer to responses.
-(BOOL)sendOperation:(NetworkOperation)op
NetworkDataType:(NetworkDataType)dataType
JsonToSend:(NSArray *)json
BackupData:(NSArray *)data
{
if(loggingMode)
{
return YES;
}
NSURLConnection *networkConnection;
NSData *send;
NSString *uuid = [self generateUUID];
NSMutableArray *connections = [[NSMutableArray alloc] init];
NSMutableURLRequest *networkRequest;
for (int i=0; i<[json count] && (data ? i<[data count] : YES); i++)
{
if(op == Login)
{
/*Grab all cookies from the server domain and delete them, this prevents login failure
because user was already logged in. Probably find a better solution like recovering
from the error*/
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:
[[NSURL alloc] initWithString:networkServerAddress]];
for (NSHTTPCookie *cookie in cookies)
{
[[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie];
}
networkRequest = [[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString:[networkServerAddress stringByAppendingString:#"/user/login"]]];
}
else if(op == StartExperiment)
{
networkRequest = [[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString:[networkServerAddress stringByAppendingString:#"/node"]]];
}
else if(op == Event || op == EndExperiment || op == SendAll)
{
networkRequest = [[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString:[networkServerAddress stringByAppendingString:#"/node"]]];
}
else if(op == Logout)
{
networkRequest = [[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString:[networkServerAddress stringByAppendingString:#"/user/logout"]]];
}
send = [[json objectAtIndex:i] dataUsingEncoding:NSUTF8StringEncoding];
//Set the headers appropriately
[networkRequest setHTTPMethod:#"POST"];
[networkRequest setValue:#"application/json"
forHTTPHeaderField: #"Content-type"];
[networkRequest setValue:[NSString stringWithFormat:#"%d", [send length]]
forHTTPHeaderField:#"Content-length"];
[networkRequest setValue:#"application/json"
forHTTPHeaderField:#"Accept"];
//Set the body to the json encoded string
[networkRequest setHTTPBody:send];
//Starts async request
networkConnection = [[NSURLConnection alloc] initWithRequest:networkRequest delegate:self];
//Successfully created, we are off
if(networkConnection)
{
[networkConnectionsAndData setValue:[[NSMutableArray alloc] initWithObjects:uuid,
[[NSNumber alloc] initWithInt:op], [[NSNumber alloc] initWithInt:dataType], [[NSMutableData alloc] init], (data ? [data objectAtIndex:i] : [NSNull null]), nil]
forKey:[networkConnection description]];
}
else //Failed to conn ect
{
NSLog(#"Failed to create NSURLConnection");
return NO;
}
}
[[self networkOperationAndConnections] setObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:[[NSMutableArray alloc] initWithObjects:connections, nil], #"connections", [[NSMutableArray alloc] init], #"errors", nil]
forKey:uuid];
return YES;
}
The dictionaries are used to keep track of the correlating data with each NSURLConnection and also to group the NSURLConnections together into one group to determine ultimate success or failure of an entire operation.
Update
AFNetworking was key in finishing this project. It not only cleaned up the code substantially, but dealt with all the threading issues inherit in sending so many requests. Not to mention with AFNetworking I could batch all the requests together into a single operation. Using blocks, like AFNetworking uses, was a much cleaner and better solution than the standard delegates for NSURLConnections.
You definitely need to allow the NSURLRequest / Connection to be operating on another thread. (Not the main thread!)
Edited for clarity**:
I noticed your comment of "//Starts async request" and I wanted to be sure you realized that your call there is not what you would expect out of a typical "asynch" function. Really its just firing off the request synchronously, but since its a web request it inherently behaves asynchronously. You want to actually place these requests on a another thread for full asynch behavior.
Everything else aside, I really suggest digging into Apple's networking example project here: MVCNetworking
As for specifics on your question, there's a couple ways to do this.
One is to keep your connection from starting immediately using initWithRequest:<blah> delegate:<blah> startImmediately:FALSE and then schedule your NSURLConnection instances on another thread's run-loop using: scheduleInRunLoop:forMode:
(Note: You then have to kick off the connection by calling start-- it's best to do this via an NSOperation + NSOperationQueue.)
Or use this static method on NSURLConnection to create/launch the connection instead of doing an alloc/init: sendAsynchronousRequest:queue:completionHandler:
(Note: this approach accomplishes pretty much same as above but obfuscates the details and takes some of the control out of your hands.)
To be honest my quick answers above won't be sufficient to finish this kind of project, and you'll need to do a bit of research to fill in the blanks, especially for the NSOperationQueue, and that's where the MVCNetworking project will help you.
Network connections are a fickle beast -- You can time-out and kill your connections even if they're running on a background thread simply by trying to perform too much work simultaneously! I would seriously reconsider opening up several thousand NSURLConnections at once, and using an NSOperationQueue would help work around this.
ADDITIONAL RESOURCES:
Here's a 3rd party library that may make your networking adventures less painful:
https://github.com/AFNetworking/AFNetworking
http://engineering.gowalla.com/2011/10/24/afnetworking/

UITableView Refresh Data

I have a UITableViewController that when opened displays a table of the following object:
class {
NSString *stringVal;
int value;
}
However, whenever this controller opens, I want it to download the data from the internet and display "Connecting..." in the status bar and refresh the stringVal and value of all of the objects. I do this by refreshing the array in the UITableViewController. However, to do this the UI hangs sometimes or even displays "blank" table cells until the operation has ended. I'm doing this in an NSOperationQueue to download the data, but I'm wondering if there's a better way to refresh the data without those weird UI bugs.
EDIT:
the UI no longer displays blank cells. This was because cellForRowAtIndexPath was setting nil values for my cellText. However, it still seems somewhat laggy when tableView.reloadData is called even though I'm using NSOperationQueue.
EDIT2:
Moreover, I have two problems: 1. the scrolling prevents the UI from being updated and 2. when the scrolling does stop and the UI starts to update, it hangs a little bit. A perfect example of what I'm trying to do can be found in the native Mail app when you view a list of folders with their unread count. If you constantly scroll the tableview, the folders unread count will be updated without any hanging at all.
Based on your response in the question comments, it sounds like you are calling [tableView reloadData] from a background thread.
Do not do this. UIKit methods, unless otherwise specified, always need to be called from the main thread. Failing to do so can cause no end of problems, and you are probably seeing one of them.
EDIT: I misread your comment. It sounds like you are not updating the UI from a background thread. But my comments about the architecture (i.e. why are you updating in a background thread AFTER the download has finished?).
You state that "when the data comes back from the server, I call a background operation..." This sounds backwards. Normally you would have your NSURLConnection (or whatever you are using for the download) run on the background thread so as not to block to UI, then call out to the main thread to update the data model and refresh the UI. Alternatively, use an asynchronous NSURLConnection (which manages its own background thread/queue), e.g.:
[NSURLConnection sendAsynchronousRequest:(NSURLRequest *)
requestqueue:(NSOperationQueue *)queue
completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler];
And just make sure to use [NSOperationQueue mainQueue] for the queue.
You can also use GCD, i.e., nested dispatch_async() calls (the outer to a background queue for handling a synchronous connection, the inner on the main queue to handle the connection response).
Finally, I will note that you in principle can update your data model on the background thread and just refresh the UI from the main thread. But this means that you need to take care to make your model code thread-safe, which you are likely to mess up at least a couple times. Since updating the model is probably not a time consuming step, I would just do it on the main thread too.
EDIT:
I am adding an example of how one might use GCD and synchronous requests to accomplish this. Clearly there are many ways to accomplish non-blocking URL requests, and I do not assert that this is the best one. It does, in my opinion, have the virtue of keeping all the code for processing a request in one place, making it easier to read.
The code has plenty of rough edges. For example, creating a custom dispatch queue is not generally necessary. It blindly assumes UTF-8 encoding of the returned web page. And none of the content (save the HTTP error description) is localized. But it does demonstrate how to run non-blocking requests and detect errors (both at the network and HTTP layers). Hope this is helpful.
NSURL *url = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
dispatch_queue_t netQueue = dispatch_queue_create("com.mycompany.netqueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(netQueue,
^{
// We are on a background thread, so we won't block UI events (or, generally, the main run loop)
NSHTTPURLResponse *response;
NSError *error;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
dispatch_async(dispatch_get_main_queue(),
^{
// We are now back on the main thread
UIAlertView *alertView = [[UIAlertView alloc] init];
[alertView addButtonWithTitle:#"OK"];
if (data) {
if ([response statusCode] == 200) {
NSMutableString *body = [[NSMutableString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
[alertView setTitle:#"Success"];
[alertView setMessage:body];
}
else {
[alertView setTitle:#"HTTP Error"];
NSString *status = [NSHTTPURLResponse localizedStringForStatusCode:[response statusCode]];
[alertView setMessage:status];
}
}
else {
[alertView setTitle:#"Error"];
[alertView setMessage:#"Unable to load URL"];
}
[alertView show];
[alertView release];
});
});
dispatch_release(netQueue);
EDIT:
Oh, one more big rough edge. The above code assumes that any HTTP status code != 200 is an error. This is not necessarily the case, but handling this is beyond the scope of this question.

How to handle different requests using connectionDidFinishLoading in the same delegate?

Whenever I do a curl call using the below code:
NSURL *url = [NSURL URLWithString:requestURL];
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:30];
if (connectionInProgress) {
[connectionInProgress cancel];
}
connectionInProgress = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];
connectionDidFinishLoading is my final destination where I can manipulate the response data and call my next methods to continue with the app . If I hard-code some specific tasks like
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
[parser setDelegate:self];
[parser parse];
[someLabel setText:parsedTextFromXMLData];
}
If I need to do another curl call to a different address, wouldn't someLabel setText always get re-set again? Is there a way to make this delegate function behave differently on each curl call? (btw, is connectionDidFinishLoading usually the right place to put the next step of codes?) If so then wouldn't it always get called again by the next curl call?
Have a look at this S.O. post for a recipe concerning NSURLConnection and multiple requests.The suggestion is doing something like this:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (connection == firstConnection) {
// do something
}
else if (connection == secondConnection) {
// do something else
}
}
EDIT: the idea here is that connectionDidFinishLoading is a method of your own delegate (so you write it). In the delegate, you store the address of each connection you create; then, when the connection comes back with the data, you tell which connection it is by comparing its address to the one you stored in the delegate. -END EDIT
Another option you have is using the ASIHTTPRequest framework, which offers a request-based (as opposed to connection-based) delegation mechanism, so each request has got a delegate object to handle the result; or, in other words, the delegate receives a reference to the request, so you can easily tell which request result you are handling.
ASIHTTPRequest offers a bunch of advantages over NSURLConnection. You can read about them in this S.O. post.
There're 2 options to do this:
you can implement a separate class, that will be responsible for handling NSURLConnection delegate stuff and create a separate instance for each request
you can use NSObject key-value methods on NSURLConnection instance for setting up some tag, that will be checked in connectionDidFinishLoading: method
For me, option 1 will be a better approach