IOS - увеличение тайм-аута для AFHTTPRequestOperationManager
Я загружаю данные JSON с очень медленного сервера. Требуется около минуты, чтобы получить перерыв с сервера. Я использую библиотеку AFNetworking, и мой код выдает ошибку "Ошибка при запросе":
NSString *urlString = [NSString stringWithFormat:@"%@/account.do?JSON&sysparm_action=getRecords",baseUrlString];
NSString *login = [[NSUserDefaults standardUserDefaults] objectForKey:@"login"];
NSString *password = [[NSUserDefaults standardUserDefaults] objectForKey:@"password"];
[manager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:login password:password];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
[self parseJsonWithAccountsData:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", operation.responseString);
[self performSelectorOnMainThread:@selector(failedWithContactsDownload) withObject:nil waitUntilDone:YES];
}];
Не удалось найти способ установить тайм-аут для AFHTTPRequestOperationManager
. Как я могу это сделать?
Ответы
Ответ 1
Метод 1.
Я думаю, что лучший способ - подкласс AFHTTPRequestSerializer
и переопределить
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(NSDictionary *)parameters
вот так:
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(NSDictionary *)parameters
{
NSMutableURLRequest *request = [super requestWithMethod:method URLString:URLString parameters:parameters];
[request setTimeoutInterval:YOUR_TIMEOUT_INTERVAL_HERE];
return request;
}
а затем
NSString *urlString = [NSString stringWithFormat:@"%@/account.do?JSON&sysparm_action=getRecords",baseUrlString];
NSString *login = [[NSUserDefaults standardUserDefaults] objectForKey:@"login"];
NSString *password = [[NSUserDefaults standardUserDefaults] objectForKey:@"password"];
[manager setRequestSerializer:YOUR_NEW_REQUEST_SERIALIZER_HERE];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:login password:password];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
[self parseJsonWithAccountsData:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", operation.responseString);
[self performSelectorOnMainThread:@selector(failedWithContactsDownload) withObject:nil waitUntilDone:YES];
}];
Метод 2
NSString *urlString = [NSString stringWithFormat:@"%@/account.do?JSON&sysparm_action=getRecords",baseUrlString];
NSString *login = [[NSUserDefaults standardUserDefaults] objectForKey:@"login"];
NSString *password = [[NSUserDefaults standardUserDefaults] objectForKey:@"password"];
[manager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:login password:password];
NSMutableURLRequest *request = [manager.requestSerializer requestWithMethod:@"GET" URLString:[[NSURL URLWithString:urlString relativeToURL:manager.baseURL] absoluteString] parameters:nil];
[request setTimeoutInterval:YOUR_TIMEOUT_INTERVAL_HERE];
AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
[self parseJsonWithAccountsData:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", operation.responseString);
[self performSelectorOnMainThread:@selector(failedWithContactsDownload) withObject:nil waitUntilDone:YES];
}];
[manager.operationQueue addOperation:operation];
Ответ 2
В библиотеке AFNetworking 2 есть метод в AFHTTPRequestSerializer
установить интервал времени ожидания запроса напрямую.
NSString *urlString = [NSString stringWithFormat:@"%@/account.do?JSON&sysparm_action=getRecords",baseUrlString];
NSString *login = [[NSUserDefaults standardUserDefaults] objectForKey:@"login"];
NSString *password = [[NSUserDefaults standardUserDefaults] objectForKey:@"password"];
[manager setRequestSerializer:[AFHTTPRequestSerializer serializer]];
[manager.requestSerializer setAuthorizationHeaderFieldWithUsername:login password:password];
[manager.requestSerializer setTimeoutInterval:TIME_OUT_INTERVAL];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
[self parseJsonWithAccountsData:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", operation.responseString);
[self performSelectorOnMainThread:@selector(failedWithContactsDownload) withObject:nil waitUntilDone:YES];
}];
Вам не нужно переопределять класс, чтобы установить интервал времени ожидания запроса.
Ответ 3
Я немного ленив, чтобы классифицировать или подклассы. Вы можете напрямую обращаться к сериализатору запросов менеджера:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer.timeoutInterval = INTERNET_TIMEOUT;
manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
Ответ 4
Создайте подкласс
self.requestOperationManager.requestSerializer = [[TimeoutAFHTTPRequestSerializer alloc] initWithTimeout:30];
TimeoutAFHTTPRequestSerializer.h
#import "AFURLRequestSerialization.h"
@interface TimeoutAFHTTPRequestSerializer : AFHTTPRequestSerializer
@property (nonatomic, assign) NSTimeInterval timeout;
- (id)initWithTimeout:(NSTimeInterval)timeout;
@end
TimeoutAFHTTPRequestSerializer.m
#import "TimeoutAFHTTPRequestSerializer.h"
@implementation TimeoutAFHTTPRequestSerializer
- (id)initWithTimeout:(NSTimeInterval)timeout {
self = [super init];
if (self) {
self.timeout = timeout;
}
return self;
}
- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(NSDictionary *)parameters
error:(NSError *__autoreleasing *)error
{
NSMutableURLRequest *request = [super requestWithMethod:method URLString:URLString parameters:parameters error:error];
if (self.timeout > 0) {
[request setTimeoutInterval:self.timeout];
}
return request;
}
@end
Ответ 5
Собственно, значение свойства timeoutInterval
игнорируется - я проверил путем отладки метода requestWithMethod:URLString:parameters:error:
Мне удалось подклассировать и переопределить метод (Swift)
class RequestSerializer: AFHTTPRequestSerializer {
override func requestWithMethod(method: String!, URLString: String!, parameters:AnyObject!, error: NSErrorPointer) -> NSMutableURLRequest {
var req = super.requestWithMethod(method, URLString: URLString, parameters: parameters, error: error)
req.timeoutInterval = self.timeoutInterval
return req
}
}