В моем проекте используется AFNetworking.
https://github.com/AFNetworking/AFNetworking
Как уменьшить время ожидания? Банкомат без подключения к Интернету блокировка сбоя не срабатывает примерно 2 минуты. До долгого ....
В моем проекте используется AFNetworking.
https://github.com/AFNetworking/AFNetworking
Как уменьшить время ожидания? Банкомат без подключения к Интернету блокировка сбоя не срабатывает примерно 2 минуты. До долгого ....
performSelector:afterDelay:...
для ручной отмены существующих операций. Пожалуйста, смотрите мой ответ для более подробной информации.Ответы:
Изменение интервала тайм-аута почти наверняка не лучшее решение проблемы, которую вы описываете. Вместо этого кажется, что на самом деле вам нужно, чтобы HTTP-клиент обрабатывал сеть, которая становится недоступной, не так ли?
AFHTTPClient
уже имеет встроенный механизм , чтобы вы знаете , когда подключение к Интернету теряется,-setReachabilityStatusChangeBlock:
.В медленных сетях запросы могут занимать много времени. Лучше доверять iOS, чтобы знать, как справляться с медленными соединениями, и отличать это от отсутствия соединения.
Чтобы расширить мои рассуждения о том, почему следует избегать других подходов, упомянутых в этой ветке, вот несколько мыслей:
performSelector:afterDelay:...
может быть опасно в многопоточных приложениях. Это открывает перед непонятными и трудными для отладки условиями гонки.источник
Я настоятельно рекомендую посмотреть на ответ Мэтта выше - хотя этот ответ не противоречит проблемам, которые он упоминает в целом, для исходного вопроса о плакатах проверка достижимости гораздо лучше подходит.
Однако, если вы все же хотите установить тайм-аут (без всех проблем, присущих и
performSelector:afterDelay:
т. Д., То запрос на перенос, упомянутый Lego, описывает способ сделать это как один из комментариев, вам просто нужно сделать:NSMutableURLRequest *request = [client requestWithMethod:@"GET" path:@"/" parameters:nil]; [request setTimeoutInterval:120]; AFHTTPRequestOperation *operation = [client HTTPRequestOperationWithRequest:request success:^{...} failure:^{...}]; [client enqueueHTTPRequestOperation:operation];
но см. предостережение @KCHarwood упоминает, что, похоже, Apple не разрешает изменять это для запросов POST (что исправлено в iOS 6 и выше).
Как указывает @ChrisopherPickslay, это не общий тайм-аут, это тайм-аут между получением (или отправкой данных). Я не знаю ни одного разумного способа сделать общий тайм-аут. В документации Apple для setTimeoutInterval говорится:
источник
timeoutInterval
это таймер простоя, а не тайм-аут запроса. Таким образом, вам нужно будет вообще не получать данных в течение 120 секунд, чтобы указанный выше код истек. Если данные поступают медленно, запрос может продолжаться бесконечно.Вы можете установить интервал тайм-аута с помощью метода requestSerializer setTimeoutInterval. Вы можете получить requestSerializer из экземпляра AFHTTPRequestOperationManager.
Например, чтобы сделать почтовый запрос с таймаутом 25 секунд:
NSDictionary *params = @{@"par1": @"value1", @"par2": @"value2"}; AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; [manager.requestSerializer setTimeoutInterval:25]; //Time out after 25 seconds [manager POST:@"URL" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { //Success call back bock NSLog(@"Request completed with response: %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { //Failure callback block. This block may be called due to time out or any other failure reason }];
источник
Я думаю, вам нужно исправить это вручную.
Я создаю подкласс AFHTTPClient и изменил
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters
метод, добавив
[request setTimeoutInterval:10.0];
в строке 236 AFHTTPClient.m. Конечно, было бы хорошо, если бы это можно было настроить, но, насколько я понимаю, в настоящее время это невозможно.
источник
Наконец выяснил, как это сделать с помощью асинхронного POST-запроса:
- (void)timeout:(NSDictionary*)dict { NDLog(@"timeout"); AFHTTPRequestOperation *operation = [dict objectForKey:@"operation"]; if (operation) { [operation cancel]; } [[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount]; [self perform:[[dict objectForKey:@"selector"] pointerValue] on:[dict objectForKey:@"object"] with:nil]; } - (void)perform:(SEL)selector on:(id)target with:(id)object { if (target && [target respondsToSelector:selector]) { [target performSelector:selector withObject:object]; } } - (void)doStuffAndNotifyObject:(id)object withSelector:(SEL)selector { // AFHTTPRequestOperation asynchronous with selector NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys: @"doStuff", @"task", nil]; AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:baseURL]]; NSMutableURLRequest *request = [httpClient requestWithMethod:@"POST" path:requestURL parameters:params]; [httpClient release]; AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease]; NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: operation, @"operation", object, @"object", [NSValue valueWithPointer:selector], @"selector", nil]; [self performSelector:@selector(timeout:) withObject:dict afterDelay:timeout]; [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeout:) object:dict]; [[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount]; [self perform:selector on:object with:[operation responseString]]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NDLog(@"fail! \nerror: %@", [error localizedDescription]); [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeout:) object:dict]; [[AFNetworkActivityIndicatorManager sharedManager] decrementActivityCount]; [self perform:selector on:object with:nil]; }]; NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease]; [[AFNetworkActivityIndicatorManager sharedManager] incrementActivityCount]; [queue addOperation:operation]; }
Я протестировал этот код, позволив своему серверу
sleep(aFewSeconds)
.Если вам нужно выполнить синхронный запрос POST, НЕ используйте
[queue waitUntilAllOperationsAreFinished];
. Вместо этого используйте тот же подход, что и для асинхронного запроса, и дождитесь срабатывания функции, которую вы передаете в аргументе селектора.источник
Основываясь на ответах других и предложении @mattt по связанным с проектом проблемам, вот быстрый совет, если вы подклассифицируете
AFHTTPClient
:@implementation SomeAPIClient // subclass of AFHTTPClient // ... - (NSMutableURLRequest *)requestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters { NSMutableURLRequest *request = [super requestWithMethod:method path:path parameters:parameters]; [request setTimeoutInterval:120]; return request; } - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method path:(NSString *)path parameters:(NSDictionary *)parameters constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block { NSMutableURLRequest *request = [super requestWithMethod:method path:path parameters:parameters]; [request setTimeoutInterval:120]; return request; } @end
Протестировано для работы на iOS 6.
источник
Разве мы не можем сделать это с помощью такого таймера:
В файле .h
{ NSInteger time; AFJSONRequestOperation *operation; }
В файле .m
-(void)AFNetworkingmethod{ time = 0; NSTtimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(startTimer:) userInfo:nil repeats:YES]; [timer fire]; operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { [self operationDidFinishLoading:JSON]; } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { [self operationDidFailWithError:error]; }]; [operation setJSONReadingOptions:NSJSONReadingMutableContainers]; [operation start]; } -(void)startTimer:(NSTimer *)someTimer{ if (time == 15&&![operation isFinished]) { time = 0; [operation invalidate]; [operation cancel]; NSLog(@"Timeout"); return; } ++time; }
источник
Здесь есть два разных значения определения «тайм-аута».
Тайм-аут как в
timeoutInterval
Вы хотите отбросить запрос, когда он бездействует (передача прекращается) дольше произвольного интервала времени. Пример: вы установили
timeoutInterval
10 секунд, вы запускаете свой запрос в 12:00:00, он может передавать некоторые данные до 12:00:23, затем соединение будет отключено в 12:00:33. Этот случай охвачен почти всеми ответами здесь (включая Джозефа Х, Мостафу Абделлатифа, Корнелиуса и Гурпартапа Сингха).Тайм-аут как в
timeoutDeadline
Вы хотите отбросить запрос, когда он достигнет крайнего срока, который произойдет позже. Пример: вы устанавливаете
deadline
10 секунд в будущем, вы запускаете свой запрос в 12:00:00, он может пытаться передать некоторые данные до 12:00:23, но соединение прервется раньше, в 12:00:10. Этот случай покрыт борисдиакуром.Я хотел бы показать, как реализовать этот крайний срок в Swift (3 и 4) для AFNetworking 3.1.
let sessionManager = AFHTTPSessionManager(baseURL: baseURL) let request = sessionManager.post(endPoint, parameters: parameters, progress: { ... }, success: { ... }, failure: { ... }) // timeout deadline at 10 seconds in the future DispatchQueue.global().asyncAfter(deadline: .now() + 10.0) { request?.cancel() }
И чтобы дать тестируемый пример, этот код должен печатать «отказ» вместо «успех» из-за немедленного тайм-аута в 0,0 секунды в будущем:
let sessionManager = AFHTTPSessionManager(baseURL: URL(string: "https://example.com")) sessionManager.responseSerializer = AFHTTPResponseSerializer() let request = sessionManager.get("/", parameters: nil, progress: nil, success: { _ in print("success") }, failure: { _ in print("failure") }) // timeout deadline at 0 seconds in the future DispatchQueue.global().asyncAfter(deadline: .now() + 0.0) { request?.cancel() }
источник
Согласитесь с Мэттом, вам не следует пытаться изменить timeoutInterval. Но вы также не должны полагаться на проверку доступности, чтобы решить, когда вы собираетесь установить соединение, вы не узнаете, пока не попробуете.
Как указано в документе Apple:
источник