NSURLSessionDataTask超时后续请求失败

nic*_*525 11 objective-c nsmutableurlrequest ios nsurlsessiondatatask

我正在创建一个NSMutableRequest:

self.req = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];
Run Code Online (Sandbox Code Playgroud)

超时设置为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];
}
Run Code Online (Sandbox Code Playgroud)

问题是服务器进入Gateway Timeout并且需要花费很多时间.我收到超时错误并向用户提供反馈,但由于超时错误,以下所有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];
}
Run Code Online (Sandbox Code Playgroud)

Tej*_*uri 5

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

[task resume];
Run Code Online (Sandbox Code Playgroud)

此行恢复任务,如果它被暂停.

尝试按如下方式调用NSURLSession:

[NSURLSession sharedSessison] instead of self.session
Run Code Online (Sandbox Code Playgroud)

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

 [[NSURLSession sharedSession]invalidateAndCancel];
Run Code Online (Sandbox Code Playgroud)

来自Apple的文档:

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

    - (void)invalidateAndCancel
Run Code Online (Sandbox Code Playgroud)

一旦失效,就会破坏对委托和回调对象的引用.会话对象无法重用.

要允许未完成的任务运行直到完成,请调用finishTasksAndInvalidate.

  - (void)finishTasksAndInvalidate
Run Code Online (Sandbox Code Playgroud)

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

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