【问题标题】:NSURLSessionDataTask completion handler not executing in command line projectNSURLSessionDataTask 完成处理程序未在命令行项目中执行
【发布时间】:2018-03-07 22:51:19
【问题描述】:

我查看了有关此问题的多个堆栈溢出帖子,并尝试实施这些修复但无济于事。这个问题的前两个答案都不起作用NSURLSessionDataTask not executing the completion handler block

这是我非常简单的代码

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
@autoreleasepool {
    NSURLSession* session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        NSLog(@"%@", json);
    }];

    [dataTask resume];
}
return 0;
}

我从来没有得到任何控制台输出。

我尝试过以不同的方式实例化会话,例如

 [NSURLSession sharedSession]

没用,

以及尝试在不同线程中执行完成块中的代码

 dispatch_sync(dispatch_get_main_queue(), ^{
   // Completion code goes here
 });

这也没用。

我也尝试了不同的 URL。我不知道为什么它不起作用。

【问题讨论】:

  • 您可以尝试记录错误并查看显示的内容。另外,您是否在 xcode 中添加了实际的 Foundation.framework?并且还执行 NSLog(@"Result: %@",json): 来查看那行代码是否被执行。
  • ps。网址很好。我在浏览器中测试过它可以工作。

标签: objective-c nsurlsession nsurlsessiondatatask


【解决方案1】:

命令行界面默认没有运行循环,因此异步任务无法工作。

你必须明确地启动和停止运行循环

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        CFRunLoopRef runloop = CFRunLoopGetCurrent();
        NSURLSession* session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
        NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"https://itunes.apple.com/search?term=apple&media=software"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
            NSLog(@"%@", json);
            CFRunLoopStop(runloop);
        }];

        [dataTask resume];
        CFRunLoopRun();
    }
    return 0;
}

您应该处理dataTask 错误以退出值!= 0

【讨论】:

    【解决方案2】:

    将此代码添加到主函数中。

     [[NSRunLoop currentRunLoop] run];
    

    这段代码将保持runloop仍然运行,从而可以完全执行请求。

    【讨论】:

    • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
    • 我的英文不好,所以写了几个字。
    【解决方案3】:

    每个进度都有一个线程,即默认在其中的主线程。一个程序通常以return 0;结尾,也就是说,你的命令行程序将在最后一行return 0;之后退出,不管那里有多少线程。

    如果你想得到请求响应,你应该让主线程等待,直到后台请求线程完成任务。查看dispatch_semaphore_signal,它对你有帮助。

    通用 iOS/macOS UI 应用程序怎么样?因为它们内部有一个名为event loop的无限循环来接收用户交互,所以不会立即调用main函数中的return 0;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-01
      • 1970-01-01
      • 2014-05-01
      • 2019-06-24
      • 1970-01-01
      • 2019-11-16
      相关资源
      最近更新 更多