我在调用 REST 服务时遇到 NSURL 连接问题。
问题是它可以通过浏览器正常工作或使用 RESTClient 来检查它,但在设备(iOS5、iOS6、模拟器)上,有时它第一次无法正常工作。超时后,它会在随后的时间工作。
它真的开始让我发疯了。
调用 this 的 main 函数通过 GCD 调用,然后在主线程上处理结果代码。200 = 验证成功,!200 = 当然失败(超时等,通过返回的整数处理)。
如前所述,问题是第一次调用它只是超时,没有返回任何内容。如果完成得足够快,后续调用往往会起作用,但如果让它等待一两分钟,则连接会在尝试访问它时超时。
我无法通过浏览器或 RESTClient 复制此行为。似乎只是iOS。我要和它一起吃香蕉。
这是进行调用的主要功能
-(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];
}
这是构建 API URL 请求函数。
// 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;
}
想法?它只返回响应代码 0 并在失败时超时。当它工作时,它工作得很好,并返回 200。
更新:这是从视图控制器调用它的方式(在按钮按下时):
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];
});
});
这样做是因为我想将 API 类与控制类分开。