Question

I have a problem with an NSURLconnection to a REST service I am calling.

The issue is it works fine through a browser or using RESTClient to check it, but on devices (iOS5, iOS6, Emulator) sometimes it will not work the first time. After the timeout, it then works subsequent times.

It's really starting to drive me nuts.

The main function which calls this is called through GCD and then processes the result code on the main thread. 200 = authentication successful, !200 = failure of course (timeout etc, handled via returned integer).

As mentioned, the problem is the first time it is called it just times out, nothing is returned. Subsequent calls tend to work if done quickly enough, but if it is left to sit for a minute or two, the connection times out against whilst trying to access it.

I cannot replicate this behaviour through a browser or RESTClient. Just iOS it would seem. I am going bananas with it.

This is the main function that makes the call

-(int)AuthUser:(ApiUser*)user{

// Authenticates the Users
// Build the URL
NSString *accessAppendix = @"/api/user/authenticate";
NSString *accessURL = [NSString stringWithFormat:@"%@%@",self.apiParameters.rootServer, accessAppendix];
NSURL *accessJSONURL= [[NSURL alloc] initWithString:accessURL];

// Setup HTTP Request Headers
NSMutableURLRequest *urlRequest = [self BuildApiUrlRequest:accessJSONURL];

// Setup dictionaries
// For posting login data

NSDictionary *Application = [[NSDictionary alloc]
                             initWithObjectsAndKeys:@"XXXXXXXXX",
                             @"Application", nil];

NSDictionary *User = [[NSDictionary alloc]
                      initWithObjectsAndKeys:
                      user.UserId,@"UserId",
                      user.Password,@"Password",
                      user.Type,@"Type",nil];

NSDictionary *Office = [[NSDictionary alloc]
                        initWithObjectsAndKeys:
                        user.office,@"Number", nil];

NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:
                            User,@"User",
                            Application,@"Application",
                            Office,@"Office",nil];

// Setup Error handler
NSError *jError;

// Serialise JSON String
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONReadingMutableContainers error:&jError];

// attach to HTTP Body
[urlRequest setHTTPBody:jsonData];

// Log URL Body
NSLog(@"Data %@",[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]);
NSLog(@"Data length: %u",[jsonData length]);    

// set Content Length
// This doesn't seem to be required really
NSString *msgLength = [NSString stringWithFormat:@"%d", [jsonData length]];
[urlRequest addValue: msgLength forHTTPHeaderField:@"Content-Length"];

NSURLResponse* response;
NSError* error = nil;

// fire Request        
NSData* result = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];

NSString *responseBody = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
NSLog(@"URL Response: %@",responseBody);
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"HttpResponse: %d",[httpResponse statusCode]);

return [httpResponse statusCode];
}

This is the Build API URL Request function.

// Builds API URL Request
-(NSMutableURLRequest*) BuildApiUrlRequest:(NSURL*)jURL
{
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:jURL];
[urlRequest setHTTPMethod:@"POST"];
NSString *authHeader = [@"Basic " stringByAppendingFormat:@"%@", self.apiParameters.rootCredentials];
[urlRequest addValue:authHeader forHTTPHeaderField:@"Authorization"];
[urlRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[urlRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[urlRequest setTimeoutInterval:10];
urlRequest.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

return urlRequest;
}

Thoughts? It just returns a response code of 0 and times out when it fails. When it works, it works quite well, and returns 200.

UPDATE: This is how it is called from the View Controller (on button push):

dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        int returnNumber = [app.pApi AuthUser:newUser];

        dispatch_async( dispatch_get_main_queue(), ^{
            [self loginResultHandler:returnNumber];
        });
    });

Done this way because I want to separate the API class right out of the controlling classes.

No correct solution

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top