我不知道我是否错过了一些明显的东西,但应该看起来正确的东西不起作用。也许我需要一双新鲜的眼睛?
我正在为我的一个应用程序测试Today Extension(小部件),在这个小部件中,我试图向Google Directions API发出请求。
我的普通应用程序本身在发出和接收请求时没有问题,但小部件本身运行不正常。
在我的普通应用程序中,我使用AFNetworking
,但AFNetworking有一些问题,[UIApplication sharedApplication]
在小部件中无法访问,所以我使用NSURLSession
发出POST请求:
NSError *error;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSString *directionsURL = [@"https://maps.googleapis.com/maps/api/" stringByAppendingString:@"directions/json"];
NSURL *url = [NSURL URLWithString:directionsURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setHTTPMethod:@"POST"];
// ------------------------------------------------------------------
// setup params
// ------------------------------------------------------------------
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
NSString *strOrigin = [[NSString alloc] initWithFormat:@"%lf,%lf", fromLocation.latitude, fromLocation.longitude];
NSString *strDestination = [[NSString alloc] initWithFormat:@"%lf,%lf", toLocation.latitude, toLocation.longitude];
[params setValue:strOrigin forKey:@"origin"];
[params setValue:strDestination forKey:@"destination"];
[params setValue:@"transit" forKey:@"mode"];
[params setValue:@"true" forKey:@"alternatives"];
NSString *GoogleAPIBrowserKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"GoogleAPIBrowserKey"];
[params setValue:GoogleAPIBrowserKey forKey:@"key"];
[params setValue:@"fewer_transfers" forKey:@"transit_routing_preference"];
DLog(@"widget params = %@", params);
NSData *postData = [NSJSONSerialization dataWithJSONObject:params options:0 error:&error];
if(error)
{
DLog(@"error setting up PostData: %@", error.localizedDescription);
}
[request addValue:[NSString stringWithFormat:@"%d", postData.length] forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:postData];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error)
{
DLog(@"Widget Error requesting route: %@", error.localizedDescription);
}
else
{
NSError *jsonError = nil;
NSDictionary* responseDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if(error)
{
DLog(@"Error converting widget response data: %@", error.localizedDescription);
}
DLog(@"Widget Google Response = %@", responseDict);
}
}];
[postDataTask resume];
我的Xcode控制台输出以下内容:
widget params = {
alternatives = true;
destination = "-31.834382,115.804225";
key = **********************;
mode = transit;
origin = "-31.833961,115.806565";
"transit_routing_preference" = "fewer_transfers";
}
Widget Google Response =
{
"error_message" = "Invalid request. Missing the 'origin' parameter.";
routes = (
);
status = "REQUEST_DENIED";
}
这让我相信我的request
的HTTP Body
在网络请求操作过程中不知何故丢失了。当日志显示"origin"是我的params字典的一部分时,它怎么会丢失?
我尝试过po data
来查看data
变量是否为nil,但它不是nil。
我为这件事伤透了脑筋。如果有人能看到我哪里出了问题并向我指出,我会很高兴的。
为什么我总是这样对自己?
简短回答
使用GET
请求包,而不是POST
。
答案很长
去散步,1小时后回家。问题解决了。
当我看到我使用AFNetworking的代码的普通应用程序版本时,我意识到我犯了一个明显的错误。
我在Today Extension中使用POST请求,而我应该像在AFNetworking代码中那样使用GET请求。
出于这个原因,新的params需要进行URL编码,而不是作为HTTP主体的一部分,所以现在的新代码是:
NSError *error;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
// ------------------------------------------------------------------
// setup URL params
// ------------------------------------------------------------------
NSMutableString *urlParams = [[NSMutableString alloc] initWithString:@"?"];
NSString *strOrigin = [[NSString alloc] initWithFormat:@"%lf,%lf", fromLocation.latitude, fromLocation.longitude];
NSString *strDestination = [[NSString alloc] initWithFormat:@"%lf,%lf", toLocation.latitude, toLocation.longitude];
NSString *GoogleAPIBrowserKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"GoogleAPIBrowserKey"];
[urlParams appendFormat:@"origin=%@&destination=%@&mode=transit&alternatives=true&key=%@&transit_routing_preference=fewer_transfers", strOrigin, strDestination, GoogleAPIBrowserKey];
NSString *directionsURL = [[NSString alloc] initWithFormat:@"https://maps.googleapis.com/maps/api/%@%@", @"directions/json", urlParams];
NSURL *url = [NSURL URLWithString:directionsURL];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:@"GET"];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error)
{
DLog(@"Widget Error requesting route: %@", error.localizedDescription);
}
else
{
NSError *jsonError = nil;
NSDictionary* responseDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if(jsonError)
{
DLog(@"Error converting widget response data: %@", error.localizedDescription);
}
DLog(@"Widget Google Response = %@", responseDict);
}
}];
[dataTask resume];
太糟糕了。对不起,我今天已经盯着屏幕看了好几个小时了:D