iOS 今天延期 POST 请求 Google 方向 API
iOS Today Extension POST request to Google Directions API
我不知道我是否遗漏了一些明显的东西,但应该看起来正确的东西不起作用。也许我需要一双新鲜的眼睛?
我正在为我的一个应用程序测试 Today Extension(小部件),在这个小部件中,我试图向 Google 方向 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' 怎么会丢失?
我已经尝试 po data
查看 data
变量是否为 nil 但它不是 nil。
我正在为这个问题绞尽脑汁。如果有人能看到我哪里做错了并指出来,我会很高兴的。
为什么我总是这样对自己?
简答
使用 GET
请求小伙子,而不是 POST
。
长答案
去散步,1 小时后回到家。问题已解决。
在查看我使用 AFNetworking 的代码的普通应用程序版本后,我意识到我的菜鸟错误。
我在 Today Extension 中使用了 POST 请求,而我应该使用 GET 请求,就像我在 AFNetworking 代码中所做的那样。
因此,新参数需要 URL 编码,而不是成为 HTTP Body 的一部分,所以新代码现在是:
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
我不知道我是否遗漏了一些明显的东西,但应该看起来正确的东西不起作用。也许我需要一双新鲜的眼睛?
我正在为我的一个应用程序测试 Today Extension(小部件),在这个小部件中,我试图向 Google 方向 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' 怎么会丢失?
我已经尝试 po data
查看 data
变量是否为 nil 但它不是 nil。
我正在为这个问题绞尽脑汁。如果有人能看到我哪里做错了并指出来,我会很高兴的。
为什么我总是这样对自己?
简答
使用 GET
请求小伙子,而不是 POST
。
长答案
去散步,1 小时后回到家。问题已解决。
在查看我使用 AFNetworking 的代码的普通应用程序版本后,我意识到我的菜鸟错误。
我在 Today Extension 中使用了 POST 请求,而我应该使用 GET 请求,就像我在 AFNetworking 代码中所做的那样。
因此,新参数需要 URL 编码,而不是成为 HTTP Body 的一部分,所以新代码现在是:
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