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";
}

这让我相信我的 requestHTTP 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