11

我正在创建一个NSMutableRequest

self.req = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];

超时设置为 10 秒,因为我不希望用户等待太久才能获得反馈。之后,我创建了一个NSURLSessionDataTask

NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response;
    if (error) {
        // this is where I get the timeout
    } 
    else if (httpResp.statusCode < 200 || httpResp.statusCode >= 300) {
        // handling error and giving feedback
    } 
    else {
        NSError *serializationError = nil;
        NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&serializationError];
    }
    [task resume];
}

问题是服务器进入网关超时并且需要很长时间。我收到超时错误并向用户提供反馈,但是由于超时错误,以下所有 API 调用都以相同的方式失败。阻止它的唯一方法是终止应用程序并重新开始。超时错误后我应该做些什么来终止任务或连接?如果我没有设置超时并且我等到我从服务器收到错误代码,那么以下所有调用都可以正常工作(但是用户等待了很多!)。

我试图取消任务:

NSURLSessionDataTask *task = [self.session dataTaskWithRequest:self.req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    NSHTTPURLResponse * httpResp = (NSHTTPURLResponse *)response;
    if (error) {
        // this is where I get the timeout
        [task cancel];
    } 
    ...
    [task resume];
}
4

4 回答 4

5

我没有看到你恢复你开始的任务。您需要声明:

[task resume];

此行恢复任务,如果它被挂起。

尝试调用 NSURLSession 如下:

[NSURLSession sharedSessison] instead of self.session

并通过以下方式使会话无效:

 [[NSURLSession sharedSession]invalidateAndCancel];

来自 Apple 的文档:

当您的应用不再需要会话时,通过调用 invalidateAndCancel(取消未完成的任务)或 finishTasksAndInvalidate(允许未完成的任务在对象无效之前完成)使其无效。

    - (void)invalidateAndCancel

一旦失效,对委托和回调对象的引用就会被破坏。会话对象不能被重用。

要允许未完成的任务一直运行直到完成,请改为调用 finishTasksAndInvalidate。

  - (void)finishTasksAndInvalidate

此方法立即返回,无需等待任务完成。一旦会话失效,就不能在会话中创建新任务,但现有任务会继续执行直到完成。在最后一个任务完成并且会话进行最后一次委托调用后,对委托和回调对象的引用将被破坏。会话对象不能被重用。

要取消所有未完成的任务,请改为调用 invalidateAndCancel。

于 2015-07-15T13:05:59.560 回答
1

您在这里最可能遇到的问题是您的任务没有取消或完成,因此阻止会话接受任何更多任务。根据 Apple 的文档

创建任务后,通过调用其 resume 方法来启动它。然后会话保持对任务的强引用,直到请求完成或失败;

正如 T_77 建议的那样,尝试使用 [NSURLSession sharedSession]

在这个时间点我还要尝试做的另一件事是尝试使用 Instruments 找出会话对象和任务之间是否创建了一个保留周期

可能发生的另一件事是请求没有正确形成并且没有执行或被挂起。当我尝试将 URL 加载到 Web 视图时,我曾经遇到过类似的问题。该页面未加载且未引发错误。尝试验证 url 请求一次。

谢谢, 苏拉杰

于 2015-07-24T10:42:42.503 回答
0

超时的最可能原因是 DNS 解析为不存在的 IP 地址,或者服务器已崩溃并需要重新启动。在任何情况下,如果一个请求因超时而失败,则更多请求也很可能因超时而失败。

您显然需要以这样一种方式编写您的应用程序,以便在服务器不回复时它可以生存。

于 2015-07-17T15:01:15.737 回答
0

您可以像下面的代码一样以不同的方式设置超时

NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.timeoutIntervalForRequest = timeout;
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:nil delegateQueue:nil];
于 2015-07-24T09:19:24.587 回答