AFNetworking – 如何设置超时时重试的请求?

我最近从ASIHTTPRequest迁移到了非常棒的AFNetworking。 但是,我连接的服务器有一些问题,有时会导致我的请求超时。 使用ASIHTTPRequest时,可以使用以下select器在发生超时时设置请求的重试计数

-setNumberOfTimesToRetryOnTimeout: 

这可以在这篇文章中进一步引用, ASIHTTPRequest是否可以重试?

这是AFNetworking,如果你不熟悉https://github.com/AFNetworking/AFNetworking#readme

我无法在AFNetworking中find等效的API,有没有人find一种解决scheme,在发生超时的情况下使用AFNetworking重试networking请求?

AFNetworking的Matt Thompson开发人员对我的回答非常友善。 下面是解释解决scheme的github链接。

https://github.com/AFNetworking/AFNetworking/issues/393

基本上,AFNetworking不支持这个function。 如下所示,由开发人员根据具体情况进行实施(摘自Matt Thompson在github上的回答)

 - (void)downloadFileRetryingNumberOfTimes:(NSUInteger)ntimes success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure { if (ntimes <= 0) { if (failure) { NSError *error = ...; failure(error); } } else { [self getPath:@"/path/to/file" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { if (success) { success(...); } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [self downloadFileRetryingNumberOfTimes:ntimes - 1 success:success failure:failure]; }]; } } 

我在我的ApiClient类中实现了私有方法:

 - (void)sendRequest:(NSURLRequest *)request successBlock:(void (^)(AFHTTPRequestOperation *operation, id responseObject))successBlock failureBlock:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failureBlock { __block NSUInteger numberOfRetries = 3; __block __weak void (^weakSendRequestBlock)(void); void (^sendRequestBlock)(void); weakSendRequestBlock = sendRequestBlock = ^{ __strong typeof (weakSendRequestBlock)strongSendRequestBlock = weakSendRequestBlock; numberOfRetries--; AFHTTPRequestOperation *operation = [self.httpManager HTTPRequestOperationWithRequest:request success:successBlock failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSInteger statusCode = [[[error userInfo] objectForKey:AFNetworkingOperationFailingURLResponseErrorKey] statusCode]; if (numberOfRetries > 0 && (statusCode == 500 || statusCode == 502 || statusCode == 503 || statusCode == 0)) { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ strongSendRequestBlock(); }); } else { if (failureBlock) { failureBlock(operation, error); } } }]; [self.httpManager.operationQueue addOperation:operation]; }; sendRequestBlock(); } 

使用示例:

 - (void)getSomeDetails:(DictionaryResultBlock)block { if (!block) { return; } NSString *urlString = @"your url string"; NSMutableURLRequest *request = [self.httpManager.requestSerializer requestWithMethod:@"POST" URLString:[[NSURL URLWithString:urlString relativeToURL:self.defaultUrl] absoluteString] parameters:nil error:nil]; // Configure you request here [request setValue:version forHTTPHeaderField:@"client-version"]; NSMutableDictionary *bodyParams = @{}; [request setHTTPBody:[NSJSONSerialization dataWithJSONObject:bodyParams options:0 error:nil]]; [self sendRequest:request successBlock:^(AFHTTPRequestOperation *operation, id responseObject) { id response = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil]; block(response, nil); } failureBlock:^(AFHTTPRequestOperation *operation, NSError *error) { block(nil, error); }]; } 

在我的情况下,我经常需要重试function,所以我想出了这个重试策略类别,这将帮助您的AFNetworking + RetryPolicy

关于AFNetworking 3.0,它可以很好地服务。

根据你的答案,你可以做一些更通用的(和棘手)通过使用块作为参数块:

 typedef void (^CallbackBlock)(NSError* error, NSObject* response); - (void) performBlock:(void (^)(CallbackBlock callback)) blockToExecute retryingNumberOfTimes:(NSUInteger)ntimes onCompletion:(void (^)(NSError* error, NSObject* response)) onCompletion { blockToExecute(^(NSError* error, NSObject* response){ if (error == nil) { onCompletion(nil, response); } else { if (ntimes <= 0) { if (onCompletion) { onCompletion(error, nil); } } else { [self performBlock:blockToExecute retryingNumberOfTimes:(ntimes - 1) onCompletion:onCompletion]; } }; }); } 

然后围绕您的asynchronousHTTP请求,如下所示:

 [self performBlock:^(CallbackBlock callback) { [...] AFHTTPRequestOperationManager *manager = [WSManager getHTTPRequestOperationManager]; [manager POST:base parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { dispatch_async(dispatch_get_main_queue(), ^(void){ if (callback) { callback(nil, responseObject); } }); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { if (callback) { NSError* errorCode = [[NSError alloc] initWithDomain:AppErrorDomain code:[operation.response statusCode] userInfo:@{ NSLocalizedDescriptionKey :error.localizedDescription}]; callback(errorCode, nil); } }]; } retryingNumberOfTimes:5 onCompletion:^(NSError *error, NSObject* response) { //everything done }]; 

这样重试等待HTTP请求完成,你不必在每个请求方法中实现重试循环。