1

I have a MacCatalyst app that can work in two ways:

  • as a classic app with a GUI
  • as a command line app without a GUI

I need to make an HTTP request to an API when the app is launched in command line. However this does not work and I don't know why.

Here is a simplified example of my case (my app is written in Objective C)

#import <UIKit/UIKit.h>

#import "AppDelegate.h"

int main(int argc, char * argv[]) {
  @autoreleasepool {
    if(argc >= 2 && [condition on argv[1]]){
      @try {
        NSURL* requestUrl = [NSURL URLWithString:@"https://google.com"];
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:requestUrl cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
        [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [request setHTTPMethod:@"GET"];

        NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest: request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
          // never called
          fprintf(stdout, "%s", [@"Request Complete" UTF8String]);
          if (error != nil) {
            // return error
            return;
          }
          // use data
        }];
        [dataTask resume];
      }@catch(NSException* e) {
        fprintf(stdout, "%s", [@"Exception" UTF8String]); // never called
      }@catch(NSError*e) {
        fprintf(stdout, "%s", [@"Error" UTF8String]); // never called
      }
    } else {
      return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
  }
}

In the above case, the dataTask completionHandler is never called, no exception or error is thrown, I get no error in the console, the script just stops after [dataTask resume].

I also tried using delegates and using background sessions with upload or download tasks but none of them worked nor thrown any error or provided any information as to what's not working or what's not allowed. When using delegates, none of the delegate callbacks is ever called.

Does anyone know what's going on ?

Goasmad
  • 69
  • 9
  • 1
    Usually, when app is being launched as a script, the app isn't kept alive: ie it "finishes" before async calls are completed. A way to do that is to keep it alive with a infinite "loop": https://stackoverflow.com/questions/28590701/multiple-workers-in-swift-command-line-tool – Larme Nov 16 '21 at 18:17
  • Thank you so much @Larme !!! you nailed it ! Thanks to your link, I was able to fix my code by encapsulating my HTTP request with ``` CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{ ...HTTP request code }); CFRunLoopRun(); ``` Could you post your answer so I can accept it ? – Goasmad Nov 16 '21 at 21:50
  • I prefer marking your question as a duplicate (as my answer doesn't have real "added valu"). While your question is in Objective-C, when the others are often in Swift, the logic behind it is the same. Since yours is a little different, other might find it, and then see the duplicate to get an answer, so maybe don't delete it, but just mark it as a duplicate. If there is no "Objective-C" equivalent on the duplicate question, you can post your solution there. – Larme Nov 17 '21 at 06:56
  • Well, with my limited knowledge of ObjectiveC, I wouldn't have found that post or wouldn't have imagined it could be relevant to my situation. So while the code to fix my problem was found in that post, it was your comment that pointed me in the right direction. I think it's fair to give you the credit for understanding my problem by accepting an answer that you would post in this thread. – Goasmad Nov 17 '21 at 09:07

0 Answers0