David Karlsson
David Karlsson

Reputation: 9686

Run http request on other thread on ios

so I want my app not to lock the GUI while sending an http request and getting the response, I made an attempt, but it complains that i use uikit outside of the mainthread, can someone please tell me the proper way of separating the http and the gui?

-(void)parseCode:(NSString*)title{

    UIActivityIndicatorView *spinner;
    spinner.center = theDelegate.window.center;
    spinner.tag = 12;
    [theDelegate.window addSubview:spinner];
    [spinner startAnimating];

    dispatch_queue_t netQueue = dispatch_queue_create("com.david.netqueue", 0);

    dispatch_async(netQueue, ^{
        NSString *url =[NSString stringWithFormat:@"http://myWebService.org/"];
        // Setup request
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
        [request setURL:[NSURL URLWithString:url]];
        [request setHTTPMethod:@"POST"];
        NSString *contentType = [NSString stringWithFormat:@"application/x-www-form-urlencoded"];
        [request addValue:contentType forHTTPHeaderField:@"Content-Type"];

        NSMutableString *data = [[NSMutableString alloc] init];
        [data appendFormat:@"lang=%@", @"English"];
        [data appendFormat:@"&code=%@", theDelegate.myView.text ];
        [data appendFormat:@"&private=True" ];
        [request setHTTPBody:[data  dataUsingEncoding:NSUTF8StringEncoding]];
        NSHTTPURLResponse *urlResponse = nil;
        NSError *error = [[NSError alloc] init];

        NSData *responseData = [NSURLConnection sendSynchronousRequest:request
                                             returningResponse:&urlResponse
                                                         error:&error];

        NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];


        dispatch_async(dispatch_get_main_queue(), ^{

            [spinner stopAnimating];
            [spinner removeFromSuperview];
            [self presentResults:result];
        });

    });

}

Upvotes: 2

Views: 1579

Answers (3)

James Holderness
James Holderness

Reputation: 23001

I don't think the problem is with your HTTP code - it's with your access of the UI from within the background thread. Specifically this line:

[data appendFormat:@"&code=%@", theDelegate.myView.text ];

You're assumedly accessing a UITextView or something similar there. You need to do that outside the background thread. Move it into a local NSString variable and then you can safely access that variable from within the background thread.

Upvotes: 1

Marcus Adams
Marcus Adams

Reputation: 53830

Instead of using NSURLConnection:sendSynchronousRequest, use NSURLConnection:initWithRequest:delegate:startImmediately:, which sends the request asynchronously. Use the NSURLConnection:connectionDidFinishLoading delegate method to handle the response.

Apple provides an example in the URL Loading System Programming Guide.

If you set startImmediately to YES, the delegate method will be called on the same run loop as the one where the request is called from. Most likely, this will be your main run loop, so you can modify the UI all you want in the delegate method, without worrying about threading issues.

Upvotes: 1

A'sa Dickens
A'sa Dickens

Reputation: 2085

i didn't look to much into it but you can always try,

[self performSelectorInBackground:@selector(parseCode:) withObject: title];

that method causes the function to run on a separate thread in the back ground, and takes little effort to implement, i use it for when i'm doing simple downloads like [NSData dataWithContentsOfURL:url]; but if you are doing something bigger you may need to do a little more work.

if you need to call the method out side of a class, then you will have to make a method with in the class that makes the call above that will then invoke the selector

Upvotes: 1

Related Questions