Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C: server requests in a thread (like AsyncTask in Android)

I would like to start a server request, you can cancel.

My idea is to start the request in a thread so that the user interface does not freeze. So you can kill the whole thread including the request with a click on a "Cancel"-button.

With Android it works: the server request gets started in a "AsyncTask" and in the "onReturn()"-method I can react as soon as the server request finish.

How can I implement this using Objective-C on iOS? My first attempt was a "NSInvocationOperation". You can cancel the operation, but it's difficult to handle when a request is completed and results are available. I think NSInvocationOperation is not the solution for my issue.

The would you recommend to me? Is NSThread the right choice for me?

Thank you very much!

like image 921
Manni Avatar asked Nov 24 '10 17:11

Manni


5 Answers

Note!

This extremely old answer is now here only for historic purposes.

The wonderful ASIHttpRequest library no longer exists; technology is totally different now.


It is unbelievably simple to do this with ASIHttpRequest.

(Asynchronous is so simple, there is no reason you would ever do it not-asynchronously.)

Here are some rough extracts that might get you started.

...
ASIFormDataRequest *request;
...
NSURL *url = [NSURL URLWithString:@"https://blah.blah/blah.cgi?blah"];
request = [ASIFormDataRequest requestWithURL:url];

[request setPostValue:@"fred" forKey:@"username"];
[request setPostValue:@"flint" forKey:@"passie"];
[request setPostValue:@"stone" forKey:@"town"];

// send up data...
[request setData:[NSData dataWithBytes:blah length:blah] forKey:@"thefile"];

// or perhaps something like...
[request setData:imageData withFileName:@"blah.png"
        andContentType:@"image/jpeg" forKey:@"photoimage"];

[request setDelegate:self];
[request setDidFinishSelector:@selector(postingDone:)];
[request setDidFailSelector:@selector(postingDoneProblem:)];
[request startAsynchronous];
...

-(void) postingDone:(ASIHTTPRequest *)request
    {
    // it worked
    }
-(void) postingDoneProblem:(ASIHTTPRequest *)request
    {
    // failed
    }

Couldn't really be any easier. You're basically just typing out the fields and values.

Per your question, here is how you cancel an "in-flight" request... just set the delegate to nil and then "cancel" it.

  [myRequest setDelegate:nil];
  [myRequest cancel];
  [myRequest release];

ASIHttpRequest is the "miracle library". If you are new to iOS, ASIHttpRequest is simply THE most used 3rd party library. Essentially, every single iPhone app of the 300,000 iPhone apps uses it.

If at all possible BE SURE to donate a few bucks to the guy -- if he stops supporting that library, 100,000 iPhone programmers are buggered!

the documentation is trivial, a child can follow it:
http://allseeing-i.com/ASIHTTPRequest/How-to-use
"Creating an asynchronous request"

it is probably - almost certainly - the most amazingly simple networking library on any platform. It is trivial to do what you describe, happily. Enjoy.

like image 172
Fattie Avatar answered Nov 11 '22 16:11

Fattie


NSURLConnection is async by default and supports cancelation as well as delegate methods when connection has been established, data has been received or whole request has been completed.

Also data transfer takes place in background so that UI stays responsive.

like image 34
Eimantas Avatar answered Nov 11 '22 17:11

Eimantas


Cocoa's built-in async networking code is not thread-based but works with run loop events, but the result (asynchronous connections) is the same.

Create an NSURLConnection with +[NSURLConnection connectionWithRequest:delegate:]. The delegate you set will be informed about the progress of the connection and can cancel it anytime with -[NSURLConnection cancel].

like image 2
Ole Begemann Avatar answered Nov 11 '22 18:11

Ole Begemann


Check out ASIHTTPRequest, specifically, the ASINetworkQueue subclass, which is described as:

ASINetworkQueue

A subclass of NSOperationQueue that may be used to track progress across multiple requests.

I've only used ASIHTTPRequest for a single synchronous request to download directly to disk, which was easy to implement, but I've heard good reports of using queues to manage multiple asynchronous server requests at once.

like image 1
Banjer Avatar answered Nov 11 '22 18:11

Banjer


One thing to note on the recommendations to use +[NSURLConnection connectionWithRequest:delegate:] is that it should only be called from the main thread as of iOS 4.

see http://blog.mugunthkumar.com/coding/ios4-issue-nsurlconnection-and-nsoperation/ for an example of how to deal with this.

like image 1
Cameron Hotchkies Avatar answered Nov 11 '22 17:11

Cameron Hotchkies