NSURLRequest Timeout IOS - iphone

I need to set timeout 15sec or 30 sec with UIRequest, but it always takes default one. Is there any way to set minimum timeout to connection.

This answer explains about the minimum value of timeoutInterval of an NSURLRequest object. If you need a smaller value, then you may do so with starting an NSTimer with the desired time and in the firing method of the timer, you cancel the connection of your NSURLConnection object. As in:
//....
connection = [[NSURLConnection connectionWithRequest:request delegate:self] retain];
[request release];
[connection start];
if (timer == NULL) {
timer = [NSTimer scheduledTimerWithTimeInterval: TimeOutSecond
target: self
selector: #selector(cancelURLConnection:)
userInfo: nil
repeats: NO];
[timer retain];
}
- (void)cancelURLConnection:(NSTimer *)timerP {
[connection cancel]; //NSURLConnection object
NSLog(#"Connection timeout.");
[timer invalidate];
}

There seems to be a problem with setting the timeout interval property at construction time:
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:240.0];
Instead set it AFTER construction:
request.timeoutInterval = 70;
Also note that there seem to be some limitations to how low you can set the interval. Read this post for more information:
https://devforums.apple.com/message/108087#108087

POST requests have a timeout minimum which is 4 minutes, I believe. The most secure way is to start a NSTimer and cancel the request when the timeout fires.

Related

ASIHTTPRequest timeout not working

The code is the following, however I can't figure out why it's not timing out even after 10 seconds has passed. Any idea?
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:sourceURL];
[request setTimeOutSeconds:5.0];
[request setDelegate:self];
[request setCompletionBlock:^{
//some code
}];
[request setFailedBlock:^{
//some code
}];
self.currentRequest_ = request;
[self.currentRequest_ startAsynchronous];
- (void)requestFailed:(ASIHTTPRequest *)request {
NSLog(#"FAILED");
}
Perhaps the request completed successfully then?
Other possibility is that there was data being received at least every 5 seconds, but the full data has not yet been received. ASI will only timeout if nothing is received for the timeout period, so if data is constantly arrived the request won't time out.
I don't think you call -[ ASIHTTPRequest startAsynchronous]... Instead add the request (which is a subclass of NSOperation) to a ASINetworkQueue (a subclass of NSOperationQueue). HTH

NSThread is blocking my GUI

I use a NSThread in order to download videos and images from a server side.It work looks and works great except the fact that when the downloading is done my GUI gets blocked until the download is complete.When the download is finished it takes a few seconds to work again.
this is how the server request is done:
- (void) repeatRequest{
NSLog(#"repeatRequest");
[NSThread detachNewThreadSelector:#selector(backgroundRequest) toTarget:self withObject:nil];
}
- (void) backgroundRequest{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSURL *url = [NSURL URLWithString:myURLStr];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
[pool drain];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
//do things
}
IMPORTANTAnd I also tried to start the ASIHTTPRequest from the GUI thread but with the same behaviour.
Any idea about what could be wrong?
EDIT:
- (void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
//internetReachable = [[Reachability reachabilityForInternetConnection] retain];
if(timer1 == nil)
{
timer1 = [NSTimer scheduledTimerWithTimeInterval:60.0 target:self selector: #selector(repeatRequest) userInfo: nil repeats: YES];
}
}
Try to run synchronous ASIHTTPRequest in your background thread, and handle results not in delegate method (requestFinished), but after [request startSynchronous];
I don't know anything about ASIHTTPRequest but i would assume its -startAsynchronous method already handles the background downloading for you. It all likelihood, it is returning immediately and your new thread is exiting. Also, you should just use [pool release] at the end of a thread method instead of [pool drain], it will be drained upon release, and you won't be leaking an NSAutoReleasePool. Does ASIHTTPRequest have a -startSynchronous (or just plain -start) method? Try using that within -backgroundRequest, as it should block the premature exit of that thread.

cancel a SynchronousRequest in iPhone SDK. (TIMEOUT Interval not working)

I've queried this forum for hours looking for an idea/answer/solution for my problem, but came up empty every time.
i have created a SynchronousRequest using the following:
NSMutableURLRequest *theRequest = [[NSMutableURLRequest alloc] initWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [params length]];
[theRequest addValue: msgLength forHTTPHeaderField:#"Content-Length"];
[theRequest setHTTPMethod:#"POST"];
[theRequest setTimeoutInterval:3.0];
[theRequest setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
[theRequest setHTTPBody: [params dataUsingEncoding:NSUTF8StringEncoding]];
NSData *aData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
the connection is established, and the data is retrieved successfully to aData.
but, when there is a connection problem, or the server is not available, the request is attempting to connect for 75 seconds which is tooooo much time for the timeout interval,
i have added the setTimeoutInterval parameter (with 3 seconds) but it does not affect the connection,
i saw some answers from people saying that i should use NSTimer, and runLoop,
but it's not clear to me how this should be implemented.
PLEASE HELP!
the users are waiting 75 seconds before they get a timeout error message! it's ridiculous
appreciate your help.
On the iPhone a minimum timeout interval is hard-coded into the framework, you can't set the timeout below 75 seconds. Apple did this because there's frequently a significant amount of lag when you're dealing with cellular data connections.
What you want to do in most situations use an asynchronous network connection (so that your GUI doesn't freeze) and allow the request to go the full 75 seconds before timing out.
Read Apple's instructions for how to set up an asynchronous connection, it's a great start.
If you really do want to set a very short timeout, you can use an NSTimer like this:
- (void)loadURL:(NSURL *)url {
/* Set up the NSURLConnection here */
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:#selector(cancelURLConnection:) userInfo:nil repeats:NO];
}
- (void)cancelURLConnection:(NSTimer)timer {
[self.connection cancel]
}
I'm not at my desktop, so that code may be buggy and it's definitely incomplete. Also note that you can't easily use a timer to kill a synchronous web requset, since the synchronous request blocks the runloop and the timer won't fire until the request is done.
may I suggest having a look at the sample code from simpleURLconnections?
From that code, the NSMutableURLRequest is sent using
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
for both retrieving and sending data (but have a look at the rest of the code). Maybe the problem lies in the sendSynchronousRequest and you can avoid using that ?
Regards
You could use some code like the following (taken from an app I'm working on) - isFinished is a global variable:
- (void)someMethod {
[[WSXMLRPCController sharedInstance] validateLicenseWithServiceURL:serviceUrl username:username password:password delegate:self];
isFinished = NO;
NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow:10]; // break the loop after 10 seconds and not finished with the request from the call above ...
while(!isFinished && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:endDate]){
if([endDate compare:[NSDate date]] == NSOrderedAscending){
[self connection:nil didFailWithError:nil forMethod:nil];
}
}
}
- (void)connection: (XMLRPCConnection *)connection didFailWithError: (NSError *)error forMethod: (NSString *)method {
isFinished = YES;
}
- (void)connection: (XMLRPCConnection *)connection didReceiveResponse: (XMLRPCResponse *)response forMethod: (NSString *)method {
isFinished = YES;
}
Probably not the cleanest solution, but it works. BTW this code is making use of the WordPress XMLRPCConnection class and delegate methods, but the same if possible with the NSURLConnection class and delegate methods.

NSOperationQueue returning __getNextReady bad access on resuming

Here's how I start the code:
m_searchTimer = [[NSTimer timerWithTimeInterval:0.5 target:self selector:#selector(launchRequest:) userInfo:nil repeats:FALSE] retain];
[[NSRunLoop mainRunLoop] addTimer:m_searchTimer forMode:NSDefaultRunLoopMode];
then in my -(void)launchRequest method:
- (void)launchRequest:(NSTimer *)timer
{
ASIHTTPRequest *req = [[[m_twitterQueue operations] lastObject] copy];
[m_twitterQueue cancelAllOperations];
[m_twitterQueue addOperation:req];
[m_twitterQueue go];
}
once I reach the - (void)go; method, I get the bad access.
Any idea is welcomed
I have found the issue.
Using ASIHTTPRequest, there is a #property named
shouldCancelAllRequestsOnFailure //Default is YES
By leaving it on, you add a request while cancelling it which makes the queue crash.
Turning it False solved the issue.

NSXMLParser initWithContentsOfURL timeout

How can I set a timeout when I am parsing a feed using initWithContentsOfURL. Sometimes our feeds return a blank response and then it will just try to parse the feed forever. I want to set a timeout of 30 seconds or so that will pop up a UIAlertView and then try and reparse the feed.
NSURL *feedURL = [[NSURL alloc] initWithString:URL];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:feedURL];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
First approach: using a delayed selector
Probably the simplest way to do this is to use NSObject's performSelector:withObject:afterDelay: method. You can define some method parsingDidTimeout as such:
- (void)parsingDidTimeout {
if(self.parsingDidComplete == NO) {
[self.parser abortParsing];
// Create your error and display it here
// Try the fetch and parse again...
}
}
This requires that you hang on to the parser as an instance variable (self.parser), so that you can cancel it from the method you define. It also requires that your parser delegate keep track of whether or not the parser has finished (self.parsingDidComplete, can be defaulted to NO and set to YES in the delegate's parserDidEndDocument: method). This is to avoid aborting a successful parse. After this is done, all it takes is a simple
[self performSelector:#selector(parsingDidTimeout) withObject:nil afterDelay:30];
and thirty seconds later, your parsing-abort code will get called, and you can do whatever it is you need to do.
Second approach: using a timer
You could make this whole approach (arguably) simpler in the timeout method by using an NSTimer instead of the NSObject method call. That way, if the parser successfully finishes, you can simply invalidate the timer, allowing you to eliminate the if clause in the parsingDidTimeout method (and, as a result, also getting rid of the BOOL ivar). The timer initialization would look like:
NSTimer *timer = [NSTimer timerWithTimeInterval:30.0
target:self
selector:#selector(parsingDidTimeout)
userInfo:nil
repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
Doesn't answer your question direction, but you'd have complete control over the request and response cycle (as well as asynchronicity without additional threads) if you used NSURLConnection to download the data. That's what initWithContentsOfURL: is doing, under the covers.
Swift 3 example using NSTimer aka Timer
func startParseTimeoutTimer() {
Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { (_) in
if (self.busy) {
self.parser?.abortParsing()
self.parser = nil
print("Show UI as NOT busy; we aborted for timeout \(Thread.current.isMainThread)")
}
}
}