Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a timeout with AFNetworking

My project is using AFNetworking.

https://github.com/AFNetworking/AFNetworking

How do I dial down the timeout? Atm with no internet connection the fail block isn't triggered for what feels like about 2 mins. Waay to long....

like image 940
jennas Avatar asked Nov 29 '11 01:11

jennas


2 Answers

Changing the timeout interval is almost certainly not the best solution to the problem you're describing. Instead, it seems like what you actually want is for the HTTP client to handle the network becoming unreachable, no?

AFHTTPClient already has a built-in mechanism to let you know when internet connection is lost, -setReachabilityStatusChangeBlock:.

Requests can take a long time on slow networks. It's better to trust iOS to know how to deal slow connections, and tell the difference between that and having no connection at all.


To expand on my reasoning as to why other approaches mentioned in this thread should be avoided, here are a few thoughts:

  • Requests can be cancelled before they're even started. Enqueueing a request makes no guarantees about when it actually starts.
  • Timeout intervals shouldn't cancel long-running requests—especially POST. Imagine if you were trying to download or upload a 100MB video. If the request is going along as best it can on a slow 3G network, why would you needlessly stop it if it's taking a bit longer than expected?
  • Doing performSelector:afterDelay:... can be dangerous in multi-threaded applications. This opens oneself up to obscure and difficult-to-debug race conditions.
like image 103
mattt Avatar answered Oct 13 '22 06:10

mattt


I strongly recommend looking at mattt's answer above - although this answer doesn't fall foul of the problems he mentions in general, for the original posters question, checking reachability is a much better fit.

However, if you do still want to set a timeout (without all the problems inherent in performSelector:afterDelay: etc, then the pull request Lego mentions describes a way to do this as one of the comments, you just do:

NSMutableURLRequest *request = [client requestWithMethod:@"GET" path:@"/" parameters:nil]; [request setTimeoutInterval:120];  AFHTTPRequestOperation *operation = [client HTTPRequestOperationWithRequest:request success:^{...} failure:^{...}]; [client enqueueHTTPRequestOperation:operation]; 

but see the caveat @KCHarwood mentions that it appears Apple don't allow this to be changed for POST requests (which is fixed in iOS 6 and upwards).

As @ChrisopherPickslay points out, this isn't an overall timeout, it's a timeout between receiving (or sending data). I'm not aware of any way to sensibly do an overall timeout. The Apple documentation for setTimeoutInterval says:

The timeout interval, in seconds. If during a connection attempt the request remains idle for longer than the timeout interval, the request is considered to have timed out. The default timeout interval is 60 seconds.

like image 35
JosephH Avatar answered Oct 13 '22 05:10

JosephH