AFNetworking离线队列

目前,我正在使用AFHTTPRequestOperationManager排队一个简单的离线请求,它似乎没有以所需的方式工作:

这里是负责任的代码,下面是不同的执行模式:

 @interface ViewController () { AFHTTPRequestOperationManager *manager; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; manager = [AFHTTPRequestOperationManager manager]; NSOperationQueue *operationQueue = manager.operationQueue; [[AFNetworkReachabilityManager sharedManager] startMonitoring]; [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status){ NSLog(@"Reachability: %@", AFStringFromNetworkReachabilityStatus(status)); switch (status) { case AFNetworkReachabilityStatusReachableViaWWAN: case AFNetworkReachabilityStatusReachableViaWiFi: NSLog(@"Operation: %@", operationQueue.operations); [operationQueue setSuspended:NO]; NSLog(@"ONLINE"); break; case AFNetworkReachabilityStatusNotReachable: default: NSLog(@"Operation: %@", operationQueue.operations); [operationQueue setSuspended:YES]; NSLog(@"OFFLINE"); break; } }]; manager.responseSerializer = [AFHTTPResponseSerializer serializer]; [manager GET:@"http://www.google.com" parameters:nil success:^(AFHTTPRequestOperation *operation, id response){ NSLog(@"success"); } failure:^(AFHTTPRequestOperation *operation, NSError *failure){ NSLog(@"failure"); }]; } 

模式1:

  • 设备在AirPlane模式

控制台输出:

 2015-03-21 16:03:54.486 OfflineSupport[928:227748] Reachability: Not Reachable 2015-03-21 16:03:54.494 OfflineSupport[928:227748] Operation: ( "<AFHTTPRequestOperation: 0x1701d0c20, state: isExecuting, cancelled: NO request: <NSMutableURLRequest: 0x170014ab0> { URL: http://www.google.com }, response: (null)>" ) 2015-03-21 16:03:54.494 OfflineSupport[928:227748] OFFLINE 2015-03-21 16:03:54.544 OfflineSupport[928:227748] failure 
  • Wifi激活

控制台输出继续:

 2015-03-21 16:04:05.594 OfflineSupport[928:227748] Reachability: Reachable via WiFi 2015-03-21 16:04:05.595 OfflineSupport[928:227748] Operation: ( ) 2015-03-21 16:04:05.595 OfflineSupport[928:227748] ONLINE 

模式2:

  • Wifi活跃

控制台输出:

 2015-03-21 16:05:43.818 OfflineSupport[934:228478] Reachability: Reachable via WiFi 2015-03-21 16:05:43.826 OfflineSupport[934:228478] Operation: ( "<AFHTTPRequestOperation: 0x1701dde20, state: isExecuting, cancelled: NO request: <NSMutableURLRequest: 0x17001ad10> { URL: http://www.google.com }, response: (null)>" ) 2015-03-21 16:05:43.826 OfflineSupport[934:228478] ONLINE 2015-03-21 16:05:43.960 OfflineSupport[934:228478] success 
  • AirPlane激活

控制台输出继续:

 2015-03-21 16:05:53.437 OfflineSupport[934:228478] Reachability: Not Reachable 2015-03-21 16:05:53.438 OfflineSupport[934:228478] Operation: ( ) 2015-03-21 16:05:53.438 OfflineSupport[934:228478] OFFLINE 

在模式1中,请求导致失败块,因为没有访问权限。 但是当设备联机时,请求不会再被执行。 有什么我在这里失踪? 我是否必须在操作队列或失败块中configuration一些东西?

参考:使用setReachabilityStatusChangeBlock设备处于脱机状态时的AFNetworking 2.0队列请求不执行任何操作 , IOS – 重新build立连接时排队请求的最佳方式

几点意见:

  1. 在模式1中,由于可达性状态块是asynchronous运行的,因此您有一些竞争条件,所以如果您启动可达性并立即添加操作,则状态可能尚未被识别为脱机,因此队列可能不是暂停,因此操作可能会立即开始(并因为您处于脱机状态而失败)。

    如果在启动可达性之前和开始任何操作之前暂停队列,问题就解决了。 如果您实际上处于离线状态,则队列将保持脱机状态,并且所添加的操作也将被暂停。 但是,如果你真的在线,可及性块将被合理快速地调用,并且队列将被立即取消挂起。 它消除了这种竞争条件。

  2. 队列的suspended状态不会影响已经启动的操作。 只影响那些还没有开始的行动。 因此,如果networking操作正在进行时连接处于脱机状态,则没有内置的机制来暂停操作,直到连接恢复为止,并且在状态改变时不重新启动操作。 如果你想要这个function,你必须自己实现。


还有几点意见:

  1. 但值得注意的是,仅仅因为可达性表示连接可用,所以并不能保证请求会成功。 你仍然需要优雅地处理失败的请求。

  2. 如果您想要更可靠的“我可以连接到特定的服务器”,您可以考虑使用managerForDomain而不是sharedManager 。 只要确保对由此产生的AFNetworkReachabilityManager保持强有力的参考,因为不像单例,它不会保持强烈的参考。

  3. AFHTTPRequestOperationManager是从版本2.x,您可能会考虑升级到最新版本(以便您使用AFHTTPSessionManager ,基于NSURLSession的实现)。 2.x中使用的NSURLConnection已被弃用。

    不幸的是, AFHTTPSessionManager不是基于NSOperation的。 但是如果你想享受“只在build立连接时发送请求”function,你可以自己把它们包装在asynchronousNSOperation子类中(参见使用NSOperation的AFNetworking 3.0 AFHTTPSessionManager ),你可以使用后台会话(参见AFNetworking 2.0和后台在为AFNetworking 2.x编写时,转移概述了使用AFHTTPSessionManager和后台会话的基本要素,后者仍然主要适用于版本3)。