Reputation: 959
I am creating a NSMutableRequest
:
self.req = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0];
The timeout is set to be 10 seconds because I don't want the user to wait too long to get a feedback.
After that I create a 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];
}
The problem is the server goes into Gateway Timeout and it takes a lot of time. I get the timeout error and I give a feedback to the user, but all the following API calls fail in the same way due to timeout error. The only way to stop it is to kill the app and start over. Is there something I should do to kill the task or the connection after a timeout error? If I don't set a timeout and I wait until I receive the error code from the server all the following calls work perfectly (But the user waits a lot!).
I tried to cancel the task:
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];
}
Upvotes: 11
Views: 3407
Reputation: 19
The problem that you are most probably encountering here is that your task is not cancelling or completing and is hence holding the session from accepting any more tasks. As per Apple's documentation
After you create a task, you start it by calling its resume method. The session then maintains a strong reference to the task until the request finishes or fails;
As T_77 suggested, try using [NSURLSession sharedSession]
Also one more thing I would try to do at this point of time is trying to find out if there is a retain cycle created between the session object and the task, using Instruments
One more thing that could be happening is that the request is not properly formed and is not executing or is hung. I had faced a similar issue once when I tried to load a URL onto a web view. The page was not loading and not throwing an error. Try verifying the url request also once.
Thanks, Suraj
Upvotes: 1
Reputation: 5148
You may set timeout in different way like following code
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfiguration.timeoutIntervalForRequest = timeout;
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration delegate:nil delegateQueue:nil];
Upvotes: 0
Reputation: 52538
The most likely cause for a timeout is either that DNS resolved to an IP address that didn't exist, or that the server has crashed and needs rebooting. In any case, if one request fails with timeout, more requests are reasonably likely to fail with timeout as well.
You obviously need to write your application in such a way that it can survive when it's servers don't reply.
Upvotes: 0
Reputation: 11201
I didnt see you resume the task you started. You need to declare:
[task resume];
This line Resumes the task, if it is suspended.
Try to call the NSURLSession as follows:
[NSURLSession sharedSessison] instead of self.session
and invalidate the session by:
[[NSURLSession sharedSession]invalidateAndCancel];
From Apple's Documentation:
When your app no longer needs a session, invalidate it by calling either invalidateAndCancel (to cancel outstanding tasks) or finishTasksAndInvalidate (to allow outstanding tasks to finish before invalidating the object).
- (void)invalidateAndCancel
Once invalidated, references to the delegate and callback objects are broken. Session objects cannot be reused.
To allow outstanding tasks to run until completion, call finishTasksAndInvalidate instead.
- (void)finishTasksAndInvalidate
This method returns immediately without waiting for tasks to finish. Once a session is invalidated, new tasks cannot be created in the session, but existing tasks continue until completion. After the last task finishes and the session makes the last delegate call, references to the delegate and callback objects are broken. Session objects cannot be reused.
To cancel all outstanding tasks, call invalidateAndCancel instead.
Upvotes: 5