views:

54

answers:

3

Hello,

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.

+1  A: 

Hello, 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

Giovanni

maggix
Yes, the problem is with `sendSynchronousRequest:`. If you run it on the main thread, your entire application blocks until the response is complete or the request has failed. That means the main run loop is blocked, so no timers or responding to events.
JeremyP
This is exactly what i want, main thread - Synchronous Request,
Dror Sabbag
therefore, connectionWithRequest will not help, since it will perform aSynchronouse request.
Dror Sabbag
A: 

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.

Wolfgang Schreurs
Hey, i see you are using the connection delegate methods, (didReceiveResponse...) therefore it means you are working asynchronous and not synchronous, will it work with sendaSynchronousRequest?
Dror Sabbag
Is there any specific reason why you would prefer using the synchronous methods over the asynchronous ones in your situation?
Wolfgang Schreurs
A: 

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.

kubi
Thanks for that, i'll check it and let you know
Dror Sabbag