NSURLSessionDataTask完成处理程序不在命令行项目中执行

时间:2018-03-07 22:51:19

标签: objective-c nsurlsession nsurlsessiondatatask

我已经查看了有关此问题的多个堆栈溢出帖子,并试图实现这些修复无济于事。这个问题的前两个答案都没有起作用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
 });

也没用。

我也尝试过不同的网址。我不知道为什么它不起作用。

3 个答案:

答案 0 :(得分:2)

默认情况下,命令行界面没有runloop,因此异步任务无法正常工作。

你必须明确地启动和停止runloop

#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

答案 1 :(得分:1)

在main函数中添加此代码。

 [[NSRunLoop currentRunLoop] run];

此代码将保持runloop仍然运行,以便可以完全执行请求。

答案 2 :(得分:1)

每个进程都有一个线程,默认情况下是主线程。程序一般以return 0;结束,也就是说,无论在那里有多少线程,你的命令行程序将在最后一行return 0;之后退出。

如果要获取请求响应,则应让主线程等待,直到后台请求线程完成任务。检查dispatch_semaphore_signal,它可以帮助您。

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