Ranjit
Ranjit

Reputation: 4636

handling response with NSURLConnection

I have created an array of NSURLConnections, as I am running through a for loop and creating multiple NSURLConnections.

Here is my code

for(int i = 0; i <count; i++)
{

 NSData *jsonData = [NSJSONSerialization dataWithJSONObject:finalJson options:NSJSONWritingPrettyPrinted error:&error];
            if (!jsonData) {
                NSLog(@"Error creating JSON object: %@", [error localizedDescription]);
            }

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"httpLink"]];


            [request setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
            [request setValue:APIKEY forHTTPHeaderField:@"X_API_KEY"];

            [request setHTTPMethod:@"POST"];
            [request setHTTPBody:jsonData];

            m_dataPush = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];

            [m_dataPushArray addObject:m_dataPush];

            [m_dataPush start];


}

Now as this a asynchronous task, the delegate functions will be called as below, I know how to handle one request , as below

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{

    if(connection == m_dataPush || connection == m_dataPull)
    {
        NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
        m_responseCode = [httpResponse statusCode];//Get status code for response

        m_ResponseData = [[NSMutableData alloc] init];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    // Append the new data to the instance variable you declared


    if(connection == m_dataPush || connection == m_dataPull)
    {
        [m_ResponseData appendData:data];
    }
}


- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    // The request is complete and data has been received
    // You can parse the stuff in your instance variable now


    if(connection == m_dataPush || connection == m_dataPull )
    {
        NSDictionary *response = [NSJSONSerialization JSONObjectWithData: m_ResponseData options: 0 error: &e];  //I am using sbjson to parse

    }   
}

But I dont know how should I handle the array of NSURLConnections in this delegate methods

Upvotes: 0

Views: 3992

Answers (2)

danh
danh

Reputation: 62686

It's just like one, except the delegate needs to keep state for all of them. In the minimal delegate code, that means collecting just the response data. To keep track of which is which, you need something unique about them (most of the time their requests, which is unique as a proxy for the urls). Since your requests are difficult to distinguish, a safer key is the pointer (as string) to the connection...

Declare the connection dictionary:

@property(strong, nonatomic) NSMutableDictionary *dictionary;

Create a connection and save it in the dictionary:

- (NSURLConnection *)connectionForRequest:(NSURLRequest *)request {
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    NSString *key = [NSString stringWithFormat:@"%p", connection];

    // create response data for the connection and save it in the dictionary
    self.dictionary[key] = [NSMutableData data];
    return  connection;
}

Look it up when you need it and return its mutable data:

- (NSMutableData *)dataForConnection:(NSURLConnection *)connection {

    NSString *key = [NSString stringWithFormat:@"%p", connection];
    return self.dictionary[key];
}

Remove it when you're done with it:

- (void)removeConnection:(NSURLConnection *)connection {

    NSString *key = [NSString stringWithFormat:@"%p", connection];
    return [self.dictionary removeObjectForKey:key];
}

Now your loop looks like this:

for(int i = 0; i <count; i++) {

NSData *jsonData = [NSJSONSerialization dataWithJSONObject:finalJson options:NSJSONWritingPrettyPrinted error:&error];
    if (!jsonData) {
        NSLog(@"Error creating JSON object: %@", [error localizedDescription]);
    }

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"httpLink"]];

    // setup the request as you do in your code
    NSURLConnection *connection = [self connectionForRequest:request];
    [connection start];
}

And the delegate methods look like this:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {

    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
    if ([httpResponse statusCode] >= 400) {
        NSLog(@"error");
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    // Append the new data to the instance variable you declared

    NSMutableData *responseData = [self dataForConnection:connection];
    [responseData appendData:data];
}


- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    NSError *e;
    NSMutableData *responseData = [self dataForConnection:connection];
    NSDictionary *result = [NSJSONSerialization JSONObjectWithData:responseData options: 0 error: &e];

    [self removeConnection:connection];

    // do whatever you do with result
}

This is fine as a general purpose pattern for creating connections and being a delegate. You can generalize creation with a method like this:

Upvotes: 3

David Bemerguy
David Bemerguy

Reputation: 1364

There are some approaches you can use: 1) Subclass NSURLConnection by adding a property that would be an id (similar as UIView has a tag property), so in the loop you set a the tag with some int. 2) Use + (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue )queue completionHandler:(void (^)(NSURLResponse, NSData*, NSError*))handler

In the case 2, inside the block you can handle each connection separately (If you need to handle each one by a different way, this approad is not valid. 3) In my opinion this is the best way --> Create a NSMutableArray and the add your connection to the array. In the callbacks you can ask

if(connection isEqual:myConnections[0]){
    // Handle it
}

if(connection isEqual:myConnections[1]){
    // Handle it and so on
}

The third approach is good when each one needs to handle by a different way

Upvotes: 0

Related Questions