Afnetworking 2.0 Queue Request When Device Is Offline with Setreachabilitystatuschangeblock Does Nothing

AFNetworking 2.0 queue request when device is offline with setReachabilityStatusChangeBlock does nothing

You need to call startMonitoring, before you call setReachabilityStatusChangeBlock

[manager.reachabilityManager startMonitoring];

If you are using AFNetworking 2.0, I suggest following:

[[AFNetworkReachabilityManager sharedManager] startMonitoring];
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
DLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status));
switch (status) {
case AFNetworkReachabilityStatusReachableViaWWAN:
case AFNetworkReachabilityStatusReachableViaWiFi:
[operationQueue setSuspended:NO];
NSLog(@"WIFI");
break;
case AFNetworkReachabilityStatusNotReachable:
default:
[operationQueue setSuspended:YES];
NSLog(@"offline, baby");
break;
}
}];

AFNetworking Offline Queue

A few observations:

  1. In pattern 1, you have a bit of a race condition because the reachability status block runs asynchronously, so if you start reachability and immediately add operation, the status may not have been identified as being offline yet, and thus the queue may not have been suspended and thus the operation may start immediately (and fail because you're offline).

    The problem is solved if you suspend the queue before starting reachability and before starting any operations. If you're actually offline, the queue will stay offline and any operations that were added will be suspended, too. But if you were really online, the reachability block will be called reasonably quickly and and the queue will be promptly be unsuspended. It eliminates this race condition.

  2. The suspended state of a queue does not affect operations that have already started. In only impacts those operations that have not yet started. So, if the connection goes offline while a network operation was in progress, there is no built in mechanism to pause the operation until the connection is restored, nor restart the operation when the status changes. If you want that functionality, you'd have to implement that yourself.


A few more observations:


  1. It's worth noting, though, that just because reachability says that connectivity is available, it doesn't guarantee that the request will succeed. You still need to gracefully handle failed requests.

  2. To the prior point, if you want a more reliable "can I connect to a particular server", you might consider using managerForDomain rather than sharedManager. Just make sure to keep a strong reference to the resulting AFNetworkReachabilityManager, because unlike the singleton, it won't keep a strong reference to itself.

  3. The AFHTTPRequestOperationManager is from version 2.x, and you might consider upgrading to the latest version (so that you use AFHTTPSessionManager, a NSURLSession based implementation). The NSURLConnection used in 2.x has been deprecated.

    The AFHTTPSessionManager is, unfortunately, not NSOperation-based. But if you want to enjoy the "send the requests only when the connection is established" functionality, you can either wrap them in asynchronous NSOperation subclass yourself (see AFNetworking 3.0 AFHTTPSessionManager using NSOperation) you can use a background session (see AFNetworking 2.0 and background transfers, while written for AFNetworking 2.x, outlines the essentials of using AFHTTPSessionManager and background session which still largely applies for version 3).

How to timeout or detect slow response in AFHTTPSessionManager in AFNetworking?

Just figure out what a reasonable timeout interval is for your app and set it on the AFHTTPSessionManager Request Serializer.

Objective-C

[manager.requestSerializer setTimeoutInterval:20.0];  

Swift

manager.requestSerializer.timeoutInterval = 20

Add something to your UI, like a UIActivityIndicatorView or a "Downloading..." message so the user knows that something is happening.

AFNetworking and No Internet Connection scenario

As of 0.9, AFHTTPClient actually has network reachability built-in (a simpler interface to Apple's aforementioned Reachability code). Just include the SystemConfiguration framework and use -setReachabilityStatusChangeBlock: to specify a response when the reachability state changes.



Related Topics



Leave a reply



Submit