Jeeva
Jeeva

Reputation: 1961

How to stop main ui thread until i get response from http request

My Target Scenario: Trying to send a simple HTTP request to my application server and get a json response in return. Based upon the json response, I need to perform a segue operation.

My Current Scenario: This happens in my system. I get json response for my HTTP request after too much delay, since my response is after delay, the segue is performed without even checking the data from response.

My requirement How to make my segue wait until I get response from the HTTP request?

[application getjsonResponse];
     if([[defaults stringForKey:@"status"] isEqual:@"success"])
        {

            return YES;

        }

These are lines of code I use. I don't want my thread to execute this if condition unless i get response for my HTTP request.

Until now what I tried:

  1. I tried thread sleep method it works sometimes and sometimes it doesn't.
  2. Until I get response, I kind of iterated a while loop.

Curious Question
When I give the same request to my application from desktop browser (Chrome) or mobile browser I get immediate response but when I am using code I seem to get result after 10 seconds delay or more. Why is this?

This is piece of code I used to send http request to my application server.

-(void)getjsonResponse
{
NSURL *url=[NSURL URLWithString: URLForApplication];
NSURLRequest *req=[NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];

NSURLSessionDataTask connection=[session dataTaskWithRequest:req completionHandler:^(NSData data, NSURLResponse response, NSError error)
 {
     if (!error){
                                     // Success
            if ([response isKindOfClass:[NSHTTPURLResponse class]])
            {
                NSError *jsonError;
                NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
                if (jsonError)
                {                       // Error Parsing JSON
                }
                else
                {   // Success Parsing JSON
                    // Log NSDictionary response:                                                      
                    NSLog(@"%@",jsonResponse);
                    {                     
                        NSString * statusCode=[[NSString alloc]init];
                        statusCode=jsonResponse[@"statusCode"];
                        _statusOtpResponse=jsonResponse[@"status"];
                        NSLog(@"status value: %@",_statusOtpResponse);
                        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
                        [defaults setObject:_statusOtpResponse forKey:@"status"];
                        [defaults setObject:statusCode forKey:@"statuscodeOtp"];
                        [defaults synchronize];                                           
                    }
                }
            }
            else
            {
                                                  //Web server is returning an error
            }
        }
        else
        {
                                              // Fail
                                              NSLog(@"error : %@", error.description);
        }

    }];
        if(connection){
            [connection resume];
        }

Upvotes: 1

Views: 279

Answers (2)

drekka
drekka

Reputation: 21893

Ok. There's a lot of inconsistencies with your question. For example, you talk about executing a segue but your code doesn't include anything to do so.

Anyway, first I'll say that stopping/pausing the main thread of your app is a bad idea. Period. The moment you do something like that, or in any way run code on the main thread that takes a noticeable amount of time to execute, you effectively render you app unresponsive, and unresponsive apps are viewed by users as being of poor quality and therefore not worth using.

Here's how I would re-write your code to execute a segue. Note the callback on the main thread.

NSURL *url = [NSURL URLWithString: URLForApplication];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];

// Do something here to indicate a server query is executing.
// For example, displaying a UIActivityIndicatorView

// Note: you had a missing '*' on this line
NSURLSessionDataTask *connection = [session dataTaskWithRequest:req completionHandler:^(NSData data, NSURLResponse response, NSError error) {

    // First error check. 
    if (error) {
        // Log and/or display alert with error message and finish.
        // Reset display to non busy mode on main thread.
        NSLog(@"error : %@", error.description);
        return;
    }

    // We're here, so request was a success
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {

        NSError *jsonError;
        NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
        if (jsonError) {
            // Log and/or display alert with error message and finish.
            // Reset display to non busy mode on main thread.
            NSLog(@"error : %@", error.description);
            return;
        }

        // We're here, so JSON parse was a success
        NSLog(@"%@", jsonResponse);
        NSString *statusCode = jsonResponse[@"statusCode"];
        NSString *statusOtpResponse = jsonResponse[@"status"];
        if (/* test variables to decide if to execute the segue */) {

            // Now we know we want to execute the segue.
            dispatch_async(dispatch_get_main_queue(), ^{
                [self performSegueWithIdentifier:@"segue-id" sender:self];
            });
        }

        // Removed your code for storing response codes in user defaults because I simply could not see why you would do that.
    }];

    // Execute
    [connection resume];

```

Upvotes: 1

Blackvenom
Blackvenom

Reputation: 687

NSURLSessionDataTask is already performed asynchronously by the system.

So if you want to perform a segue after you receive data from the request, just place your segue-code inside the completion block.

In your case, just after you process the response data, for example after the line:

[defaults synchronize];  

Be aware, that you should dispatch to the main thread first, before doing work on the main thread again.

dispatch_async(dispatch_get_main_queue(), ^{
   // YOUR SEGUE HERE
});

Upvotes: 0

Related Questions