how to use sendAsynchronousRequest:queue:completionHandler:

IphoneIosNsurlconnection

Iphone Problem Overview


Two part question

Part one: I am trying to create an ASynchronous request to my database. I am currently doing it Synchronously however I want to learn both ways to better my understanding of whats going on.

Currently I have set up my Synchronous call like this.

- (IBAction)setRequestString:(NSString *)string
{
    //Set database address
    NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:@"http://127.0.0.1:8778/instacodeData/"]; // imac development
    
    //PHP file name is being set from the parent view
    [databaseURL appendString:string];
    
    //call ASIHTTP delegates (Used to connect to database)
    NSURL *url = [NSURL URLWithString:databaseURL];
    
    //SynchronousRequest to grab the data
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSError *error;
    NSURLResponse *response;
    
    NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    if (!result) {
        //Display error message here
        NSLog(@"Error");
    } else {
        
        //TODO: set up stuff that needs to work on the data here.
        NSString* newStr = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
        NSLog(@"%@", newStr);
    }
}

I think what I need to do is replace the call

NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

with the ASynchronous version

sendAsynchronousRequest:queue:completionHandler:

however I'm not sure what to pass to queue or completionHandler... Any examples/solutions would be greatly appreciated.

Part two: I have been reading about multi tasking and I would like to support it by making sure my connection requests complete if there is an interrupt. I have been following this example

In it it explains how to gain more time if an interrupt occurs, I understand what its doing.. but not how to apply it to this connection? if you have any examples/tutorials to help me figure out how to apply it that would be awesome!

Iphone Solutions


Solution 1 - Iphone

PArt 1:

NSURL *url = [NSURL URLWithString:urlString];

NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
    if ([data length] > 0 && error == nil)
        [delegate receivedData:data];
    else if ([data length] == 0 && error == nil)
        [delegate emptyReply];
    else if (error != nil && error.code == ERROR_CODE_TIMEOUT)
        [delegate timedOut];
    else if (error != nil)
        [delegate downloadError:error];
}];

Solution 2 - Iphone

Here is a sample:

NSString *urlAsString = @"http://www.cnn.com";
NSURL *url = [NSURL URLWithString:urlAsString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];


[NSURLConnection
		 sendAsynchronousRequest:urlRequest
		 queue:[[NSOperationQueue alloc] init]
		 completionHandler:^(NSURLResponse *response,
							 NSData *data,
							 NSError *error) 
		{
		 
		 if ([data length] >0 && error == nil)
		 {
			 
                        // DO YOUR WORK HERE
			 
		 }
		 else if ([data length] == 0 && error == nil)
		 {
			 NSLog(@"Nothing was downloaded.");
		 }
		 else if (error != nil){
			 NSLog(@"Error = %@", error);
		 }
		 
	 }];

Solution 3 - Iphone

For the queue param, try this magic:

[NSOperationQueue mainQueue]

This works great if you are updating the UI on completion of the request since main queue is the main thread. It essentially gives you the previous behavior of NSURLConnection. If however you plan on writing to file or decompressing then you can complete on a background queue and then dispatch async back to the main queue for the UI updates.

Solution 4 - Iphone

I have been working on a similar problem, I posted this question and got a clear answer here, I hope that helps with Part 2.

For part 1 what the others mentioned here are good but you need to add another check (I have modified an answer below). It is possible that your request will return say a 404 Error (page not found) in which case you will not get and error and data will be > 0. The 200 is a good response, you could also check the StatusCode for 404 or whatever.

     [NSURLConnection
     sendAsynchronousRequest:urlRequest
     queue:[[NSOperationQueue alloc] init]
     completionHandler:^(NSURLResponse *response,
                         NSData *data,
                         NSError *error) 
    {
    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
     if ([data length] >0 && error == nil && [httpResponse statusCode] == 200)
     {

                    // DO YOUR WORK HERE

     }

Solution 5 - Iphone

Since sendAsynchronousRequest:urlRequest queue:queue completionHandler: has been deprecated in iOS 9, and it will suggest to use NSURLSession's -dataTaskWithRequest:completionHandler: instead. It is available since iOS 7 and later.

Original:

 NSURL *URL = [NSURL URLWithString:@"http://example.com"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];

 [NSURLConnection sendAsynchronousRequest:request
                                    queue:[NSOperationQueue mainQueue]
                        completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
     // ...
 }];

By NSURLSession:

 NSURL *URL = [NSURL URLWithString:@"http://example.com"];
 NSURLRequest *request = [NSURLRequest requestWithURL:URL];

 NSURLSession *session = [NSURLSession sharedSession];
 NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                         completionHandler:
     ^(NSData *data, NSURLResponse *response, NSError *error) {
         // ...
     }];

 [task resume];

Solution 6 - Iphone

sendAsynchronousRequest has been deprecated in Swift. Move to dataTaskWithRequest, luckily it is used pretty much the same way.

if let url = NSURL(string:"http://your_url") {

    let request:NSURLRequest = NSURLRequest(URL: url)
    let config = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: config)
    
    let task = session.dataTaskWithRequest(request, completionHandler: {(data, response, error) in
    
    });
    
    task.resume()
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionC.JohnsView Question on Stackoverflow
Solution 1 - IphonembhView Answer on Stackoverflow
Solution 2 - IphoneFleaView Answer on Stackoverflow
Solution 3 - IphonemalhalView Answer on Stackoverflow
Solution 4 - IphoneRecycled SteelView Answer on Stackoverflow
Solution 5 - IphoneAechoLiuView Answer on Stackoverflow
Solution 6 - IphoneBhavesh PatelView Answer on Stackoverflow