AFHTTPRequestOperation 超时

Posted

技术标签:

【中文标题】AFHTTPRequestOperation 超时【英文标题】:AFHTTPRequestOperation times out 【发布时间】:2014-04-29 17:41:43 【问题描述】:

我的应用中有一些网络服务调用。这是我如何称呼它们的示例

+(void) login:(NSDictionary *) loginParams 

    AppDelegate *appDelegate  = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSString * URLString = [MPTLogin getLoginWSAddress];
    AFHTTPClient* client = [[AFHTTPClient alloc]initWithBaseURL:[NSURL URLWithString:URLString]];
    NSMutableURLRequest *request = [client requestWithMethod:@"POST"
                                                    path:URLString
                                              parameters:loginParams];
    AFHTTPRequestOperation* operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) 
        [[NSNotificationCenter defaultCenter] postNotificationName:@"didSuccessfullyAttemptLogin" object:nil userInfo:nil];

     failure:^(AFHTTPRequestOperation *operation, NSError *error) 
        if ([operation.response statusCode] == 401)
            [[NSNotificationCenter defaultCenter] postNotificationName:@"invalidUserNameOrPassword" object:self userInfo:nil];

        else
            [[NSNotificationCenter defaultCenter] postNotificationName:@"didFailedAttemptLogin" object:self userInfo:nil];
    ];

    [operation start];

问题是,如果在 5-15 分钟内没有调用任何 Web 服务,则下一个调用的 Web 服务会超时。然后,之后的任何调用只需要一秒钟的时间即可完成,直到几分钟内没有调用。然后同样的事情再次发生。

这只发生在设备上。模拟器很好。另外,这不是wifi问题。我完全不知道如何调试它。

更新:所以我检查了服务器日志,呼叫没有按时到达。 我也尝试使用Charles Proxy。最离奇的事情发生了。当代理打开时,不会发生超时。事实上,电话几乎是立即发生的。但是当我取消代理时,会发生同样的问题。

更新:这不是 wifi 问题,因为我们已经在不同的设备、不同的 wifi 连接、不同的状态下进行了尝试。

更新所以我最终将超时设置为 150 秒。现在,我的超时时间减少了,但问题是每当我超时时,控制台都会说它需要 60 秒。超时代码也是-1001

【问题讨论】:

loginParams 和 URLString 的示例值是什么?它正在使用代理但不使用代理?服务器可以认为该请求是垃圾邮件请求吗?只是随机猜测。 loginParams 是字典:@@"userName":@"simpleString",@"password":@"smipleString",@"deviceName":@"Somestring_anInt"; 你设置的超时时间是在服务器端还是 NSMutableURLRequest 上的 timeoutInterval?如果是 NSMutableURLRequest,150 秒太长了。你能截屏或粘贴超时错误日志吗? 【参考方案1】:

根据我使用 Web 服务和 AFHTTPRequest 的经验,请求超时主要与服务器/网络相关。如果您确认服务器没有任何问题,我认为您能做的最好的事情就是将请求发送到 timeoutInterval(例如:15 秒)。接下来,如果您仍然收到请求超时错误,您可以尝试N次相同的操作。

例如,您可以执行以下操作:-

重试 3 次调用函数:

[ServerRequest yourMethodName:yourLoginDict with:3];

功能:-

+(void)yourMethodName:(NSDictionary *) loginParams with:(NSUInteger)ntimes 

if (ntimes <= 0) 
    NSLog(@"Request failed after trying for N times");

else

    NSDictionary * postDictionary = loginParams;
    NSError * error = nil;
    NSData * jsonData = [NSJSONSerialization dataWithJSONObject:postDictionary options:NSJSONWritingPrettyPrinted error:&error];
    NSString * urlString = [NSString stringWithFormat:@"%@",@"YOUR URL"];

    //Give the Request 15 seconds to load
    NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15.0];
    [urlRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [urlRequest setHTTPMethod:@"POST"];
    [urlRequest setHTTPBody:jsonData];

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:urlRequest];
    [operation  setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) 
        NSLog(@"Successful request");
    
    failure:^(AFHTTPRequestOperation *operation, NSError *error) 
        NSLog(@"Request Failed at %d: %@",ntimes,error);

        //If the request failed, call again with ntimes-1
        [self yourMethodName:loginParams with:ntimes-1];
        
     ];
    [operation start];
 

我希望这会有所帮助。

【讨论】:

感谢您的回答。我要试试这个。所以这个问题导致了两件事。第一个只是很长的等待,第二个是失败。这将避免失败,但我仍然希望避免等待。 没问题。如果等待时间过长,可以将 timeoutInterval 减小到 10 或 5 秒。这真的取决于你需要什么。如果您一直面临这个问题,我认为问题实际上出在连接或服务器端。不是你的前端代码的问题。 也许您可以在尝试完代码后报告任何性能或问题,我会看看我能进一步提供什么帮助。【参考方案2】:

//创建推特账号 -(void)createTwitterAccountWithDictionary:(NSDictionary*)dictionary WithCompletionBlock:(void(^)(user *userObj,NSString *errorMessager))completionBlock

AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager manager] initWithBaseURL:BASE_URL];
[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeGradient];

[manager POST:KCreateTwitterAccount parameters:dictionary success:^(AFHTTPRequestOperation *operation, id responseObject) 
    NSLog(@"Request url:%@",operation.request.URL);
    NSLog(@"Response: %@", responseObject);
    if ([responseObject[@"status"]isEqualToString:@"SUCCESS"]) 
        user *userObj = [[user alloc]initWithUserDictionary:responseObject[@"data"]];
        completionBlock(userObj,nil);
        [SVProgressHUD showSuccessWithStatus:@"Success"];
    
    else
        [SVProgressHUD dismiss];
        completionBlock(nil,responseObject[@"message"]);
    
 failure:^(AFHTTPRequestOperation *operation, NSError *error) 
    NSLog(@"Request url:%@",operation.request.URL);
    NSLog(@"Error: %@", error);
    [SVProgressHUD showErrorWithStatus:@"Failure"];
];

在 AFURLResponseSerialization.m 中 做了这些改变

- (instancetype)init 
    self = [super init];
    if (!self) 
        return nil;
    
#pragma mark - did changes
    //add this @"text/html"
    self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html", nil];

    return self;

【讨论】:

以上是关于AFHTTPRequestOperation 超时的主要内容,如果未能解决你的问题,请参考以下文章

未知接收者'AFHTTPRequestOperation';你的意思是'AFHTTPRequestSerializer'

Swift错误无法转换类型'(AFHTTPRequestOperation?,AnyObject?)->()的值

AFHTTPRequestOperation setCacheResponseBlock 无法转换类型的值

AFNetworking + AFHTTPRequestOperation 无法保存数组

AFNetworking 2 使用 AFHTTPRequestOperation 进行身份验证

在 AFHTTPRequestOperation 失败时显示 UIAlertView