Reputation: 9686
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
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
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
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