0

I have looked on multiple stack overflow posts regarding this issue and attempted to implement those fixes to no avail. Neither of the top two answers from this question worked NSURLSessionDataTask not executing the completion handler block

Here is my very simple code

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

I'm never getting any console output.

I have tried instantiating the session in different ways, like

 [NSURLSession sharedSession]

which didn't work,

as well as trying to execute the code in the completion block in a different thread

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

which also didn't work.

I've also tried different URL's. I have no idea why it's not working.

Dalton Sweeney
  • 1,108
  • 3
  • 11
  • 24
  • You can try log the error as well see what that shows. Also, did you add the actual Foundation.framework in your xcode? And also do NSLog(@"Result: %@",json): instead to see did that line of code get executed or not. – GeneCode Mar 08 '18 at 08:37
  • ps. The URL is fine. I tested it in browser it works. – GeneCode Mar 08 '18 at 08:38

3 Answers3

3

A command line interface does not have a runloop by default so asynchronous tasks cannot work.

You have to start and stop the runloop explicitly

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

You should handle the dataTask error to exit with a value != 0

vadian
  • 274,689
  • 30
  • 353
  • 361
1

add this code in main function.

 [[NSRunLoop currentRunLoop] run];

this code will keep the runloop still run,so that the request can be executed totally.

foolmcode
  • 11
  • 4
1

Every progress has one thread, that is, main thread in it by default. A program ends up with return 0; in general, that is, your command line program will be exited after the last line return 0; no matter how many threads alive there.

If you want to get the request response, you should let the main thread wait until the background request thread finishes the task. Check the dispatch_semaphore_signal out, it helps you.

How about the generic iOS/macOS UI application? Because they have an infinite loop called event loop inside to receive the user interactions, so the return 0; in the main function won't be called immediately.

Itachi
  • 5,777
  • 2
  • 37
  • 69