【问题标题】:iOS - Increase timeout for AFHTTPRequestOperationManageriOS - 增加 AFHTTPRequestOperationManager 的超时时间
【发布时间】:2014-02-09 20:28:54
【问题描述】:

我正在从非常慢的服务器下载 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 设置超时的方法。我该怎么做?

【问题讨论】:

标签: ios cocoa-touch afnetworking afnetworking-2


【解决方案1】:

在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];
    }];

您无需重写该类来设置请求超时间隔。

【讨论】:

    【解决方案2】:

    方法一。

    我认为最好的方法是继承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];
        }];
    

    方法二

    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];
    

    【讨论】:

    • 感谢您的回答!实际上我不得不覆盖 - (NSMutableURLRequest *)requestWithMethod:(NSString *)method URLString:(NSString *)URLString parameters:(NSDictionary *)parameters error:(NSError *__autoreleasing *)error 也,但你的答案是绝对正确的!
    • PgmFreek 的解决方案是 2.0 的解决方案。
    【解决方案3】:

    我有点懒得分类或子类化。您可以直接访问管理器的请求序列化程序:

    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.requestSerializer.timeoutInterval = INTERNET_TIMEOUT;
    manager.requestSerializer.cachePolicy = NSURLRequestReloadIgnoringLocalAndRemoteCacheData;
    

    【讨论】:

    • 不幸的是它不起作用。在调试时,我发现使用此方法设置时不遵守超时。目前似乎只有子类化有效。
    • 嗯...我使用 AFNetworking 2.5.4 运行的测试在 1 到 120 秒之间改变超时都运行良好。
    • 嗯,这很奇怪。对我来说,无论我设置什么值(使用默认的 AFNetworking 管理器单例),AFNetworking 2.5.4 的解决方案超时始终为 ~60 秒。不过感谢您的检查,贡献良多!
    • @Vive 它只在我创建一个新的 requestSerializer AFJSONRequestSerializer *serializer = [AFJSONRequestSerializer serializer]; manager.requestSerializer = serializer; // Then execute the above code 时才对我有用
    【解决方案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
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2010-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-11
        • 2014-04-16
        • 1970-01-01
        • 1970-01-01
        • 2023-03-20
        相关资源
        最近更新 更多