【问题标题】:Objective C - HTTP GET Request API目标 C - HTTP GET 请求 API
【发布时间】:2017-09-28 20:35:10
【问题描述】:

我一直在尝试查询 Tesco 的 API 服务。尽管我已经在 Python 上进行了舒适的管理,但我在使用 Objective C 发出请求时遇到了一些麻烦。输出中没有记录任何内容。任何帮助,将不胜感激。程序代码如下:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSURLSessionConfiguration *defaultSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
        NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultSessionConfiguration];

        NSURL *url = [NSURL URLWithString:@"https://dev.tescolabs.com/product/?gtin=4548736003446"];
        NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];

        NSString *postParams = @"subscription key=93a6e21eed2e4ca3a858a0f1fc5aaf03";
        NSData *postData = [postParams dataUsingEncoding:NSUTF8StringEncoding];

        [urlRequest setHTTPMethod:@"GET"];
        [urlRequest setHTTPBody:postData];

        NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            NSLog(@"Response: %@",response);
            NSLog(@"Data: %@",data);
            NSLog(@"Error: %@",error);
        }];
        [dataTask resume];
    }
    return 0;
}

【问题讨论】:

  • 你检查完成处理程序中的错误了吗?
  • 是的,我刚刚检查了完成处理程序中的错误,没有记录任何内容。还更新了 URL,这里是 API 的来源:devportal.tescolabs.com/docs/services
  • @Benge 尝试 error.localizedDescription
  • 当你说什么都没有被记录时,你的意思是错误是 nil,还是 NSLogs 永远不会被执行?
  • NSLog 没有被执行。 @ravi.p 试过了,没有记录错误。

标签: objective-c nsurlsession


【解决方案1】:

我别无选择,只能给出一个答案……注意运行循环代码:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSURLSessionConfiguration *defaultSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
        NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultSessionConfiguration];

        NSURL *url = [NSURL URLWithString:@"https://dev.tescolabs.com/product/?gtin=4548736003446"];
        NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];

        NSString *postParams = @"subscription key=93a6e21eed2e4ca3a858a0f1fc5aaf03";
        NSData *postData = [postParams dataUsingEncoding:NSUTF8StringEncoding];

        [urlRequest setHTTPMethod:@"GET"];
        [urlRequest setHTTPBody:postData];

        __block BOOL done = NO;
        NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            NSLog(@"Response: %@",response);
            NSLog(@"Data: %@",data);
            NSLog(@"Error: %@",error);
            done = YES;
        }];
        [dataTask resume];

        while (!done) {
            NSDate *date = [[NSDate alloc] initWithTimeIntervalSinceNow:0.1];
            [[NSRunLoop currentRunLoop] runUntilDate:date];
        }
    }
    return 0;
}

【讨论】:

  • 迄今为止的最佳答案。 NSRunLoop 工作并最终得到了回应。错误为空,状态码为 500。顺便说一句,隐藏密钥等详细信息。谢谢老兄。
  • @Benge 请阅读文档,它说将密钥分配为标题字段,而不是在帖子正文中。 RTFM ;) devportal.tescolabs.com/docs/services/57f247f9e2813e07d8663943/…
  • Mazyod,将其更改为标题字段。谢谢。
  • 状态OK并返回数据。
【解决方案2】:

基本上你需要一个运行循环来执行后台任务。

您的请求不起作用,因为使用 GET 请求时未考虑正文 POST 数据。
所有参数都必须在 URL 中传递。

要实现运行循环,只需使用CFRunLoopRun()CFRunLoopStop()

不要将NSRunLoop ... runUntilDate 与while 循环一起使用

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSURLSessionConfiguration *defaultSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
        NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultSessionConfiguration];

        NSURL *url = [NSURL URLWithString:@"https://dev.tescolabs.com/product/? ... "];

        NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithURL: url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            NSLog(@"Response: %@",response);
            NSLog(@"Data: %@",data);
            NSLog(@"Error: %@",error);
            CFRunLoopStop(CFRunLoopGetCurrent());
            exit(EXIT_SUCCESS);
        }];
        [dataTask resume];
    }

    CFRunLoopRun();
    return 0;
}

【讨论】:

  • +1 谢谢,我真的很喜欢你的方法。但是,在 while 循环中正确使用不会收集垃圾的保留/释放对象的真正危害是什么?
  • 同理,为什么不使用带有循环的 NSRunLoop?
  • 没有害处。这只是一种尴尬且低效的方式。
  • @Benge 只要你能避免轮询(这种循环),就去做。 不要问,告诉不要等待,通知
  • @Vadian,干杯。
【解决方案3】:

-dataTaskWithRequest:completionHandler: 是异步的。您正在排队一个稍后会完成的操作,然后在它完成之前退出程序。

您需要一种机制来等待数据任务完成后再退出程序。

有关等待机制的示例,请参阅:https://stackoverflow.com/a/34200617/1298400

【讨论】:

  • 我不太确定是否使用信号量,因为回调可能是在主线程上传递的。更喜欢使用[NSRunLoop runUntilDate:]
  • 是的,信号量方法本质上会阻塞主线程。
  • @Mazyod 无论他使用什么方法,他都必须阻塞主线程。
  • @JefferyThomas Nope .. 看看NSRunLoop
  • @Mazyod 看看他的代码示例。他退出主线程。就这样,程序结束。如果他不阻塞主线程,就没有程序运行来执行他的回调。
【解决方案4】:

试试这个你需要在这个请求的头中传递订阅密钥

NSDictionary *headers = @{ @"ocp-apim-subscription-key": @"YourKey"};

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"YourURL"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"GET"];
[request setAllHTTPHeaderFields:headers];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                if (error) {
                                                    NSLog(@"%@", error);
                                                } else {
                                                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                    NSLog(@"%@", httpResponse);
                                                }
                                            }];
[dataTask resume];

【讨论】:

  • @chronikum 完成
  • 非常好的方法,不幸的是我在输出中仍然没有得到任何响应。
  • @Benge 它工作正常,所以你能描述一下你面临的问题是什么
【解决方案5】:
#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        NSURLSessionConfiguration *defaultSessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
        NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration:defaultSessionConfiguration];

        NSURL *url = [NSURL URLWithString:@"https://dev.tescolabs.com/product/? ... "];

        NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithURL: url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            NSLog(@"Response: %@",response);
            NSLog(@"Data: %@",data);
            NSLog(@"Error: %@",error);
            CFRunLoopStop(CFRunLoopGetCurrent());
            exit(EXIT_SUCCESS);
        }];
        [dataTask resume];
    }

    CFRunLoopRun();
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-10
    • 2015-08-20
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-05
    • 2018-11-29
    相关资源
    最近更新 更多