Wait for an NSURLConnection

2019-08-27 20:04发布

问题:

I have code that sends away a HTTP POST connection. I want the method to wait until I get a response from the server for it to continue. The reason I am doing it this way is because I am integrating new code (asynchronous post vs the old synchronous post) into our application and I am looking for minimal change throughout the application.

The old method was as follows:

-(NSData*) postData: (NSString*) strData;

The application would call it and send it a strData object and it would lock the main thread until it got something back. This was inefficient but it worked well, but due to timeout constraints I have to change it.

So my new method (posting the complete method here) is as follows:

-(NSData*) postData: (NSString*) strData
{
    //start http request code
    //postString is the STRING TO BE POSTED
    NSString *postString;
    //this is the string to send
    postString = @"data=";
    postString = [postString stringByAppendingString:strData]; 
    NSURL *url = [NSURL URLWithString:@"MYSERVERURL"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    NSString *msgLength = [NSString stringWithFormat:@"%d", [postString length]];
    //setting prarameters of the POST connection
    [request setHTTPMethod:@"POST"];
    [request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [request addValue:msgLength forHTTPHeaderField:@"Content-Length"];
    [request addValue:@"en-US" forHTTPHeaderField:@"Content-Language"];
    [request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
    [request setTimeoutInterval:20]; //one second for testing purposes
    NSLog(@"%@",postString);    
    NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
    [connection start];
    //end http request code
    return receivedData; //this is set by a delegate somewhere else in the code
}

It sends the code fine, but of course (and as expected), it does not receive it fast enough to be returned correctly.

What do you recommend I can do to "stop" that method to wait to return anything until something is received? I've tried setting a while loop that waited on a BOOL that would be set to YES when all data was received, but that loop prevented the code from sending at all. I also tried throwing the contents of this method into another method and calling it to performSelectorInBackground, but of course, that didn't work either. I'm running out of ideas and I'd really appreciate the help.

回答1:

Doing any sort of synchronous comms on the main thread is a bad idea, but if you can't re-architect at this point then take a look at:

+[NSURLConnection sendSynchronousRequest:returningResponse:error:]

The documentation can be found here. From the discussion:

A synchronous load is built on top of the asynchronous loading code made available by the class. The calling thread is blocked while the asynchronous loading system performs the URL load on a thread spawned specifically for this load request. No special threading or run loop configuration is necessary in the calling thread in order to perform a synchronous load.

But seriously, take a look and how much work would be involved in performing the request asynchronously and receiving a notification when the request is complete. The whole experience for the user is going to be much better.



回答2:

You are actually performing an asynchronous request there.

In order to do a synchronous request, you should use + (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error in the NSURLConnection Class.

It is indeed a bad idea though to block the app while you are doing this and therefore it is usually discouraged.

Cheers