You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

命令行模式下MacCatalyst应用发送HTTP请求无回调问题求解

问题原因
  • 主线程RunLoop未持续运行:NSURLSession的异步回调依赖所属线程的RunLoop进行事件调度,你当前的命令行分支代码执行完[dataTask resume]后,没有任何逻辑阻止主线程退出,@autoreleasepool块执行结束后进程直接终止,回调自然不会被触发。
  • 缺少网络权限(可选触发条件):Mac Catalyst应用默认开启App Sandbox的情况下,没有勾选出站网络连接权限的话,网络请求会静默失败,不会抛出显式错误。
解决方案

方案1:使用信号量等待异步请求完成

这是最简单的适配方式,直接阻塞当前线程直到请求回调执行完毕,适合轻量命令行场景:

int main(int argc, char * argv[]) {
  @autoreleasepool {
    if(argc >= 2 && [condition on argv[1]]){
      dispatch_semaphore_t sem = dispatch_semaphore_create(0);
      @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) {
          fprintf(stdout, "%s", [@"Request Complete" UTF8String]);
          if (error != nil) {
            fprintf(stderr, "Request error: %s\n", error.localizedDescription.UTF8String);
          } else {
            // 处理返回数据
          }
          dispatch_semaphore_signal(sem);
        }];
        [dataTask resume];
      } @catch(NSException* e) {
        fprintf(stdout, "%s", [@"Exception" UTF8String]);
        dispatch_semaphore_signal(sem);
      }
      // 等待信号量触发,最多等待11秒(比请求超时多1秒避免死等)
      dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, 11 * NSEC_PER_SEC));
      // 处理完所有逻辑后直接退出进程
      exit(0);
    } else {
      return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
  }
}

方案2:手动运行RunLoop

如果你的命令行模式需要处理多个异步任务,不希望用信号量阻塞,可以手动启动RunLoop并保活,直到所有任务完成后终止RunLoop:

// 声明全局标记位控制RunLoop运行
static BOOL shouldKeepRunning = YES;

// 回调内修改标记位
dispatch_async(dispatch_get_main_queue(), ^{
  shouldKeepRunning = NO;
});

// 启动RunLoop循环
while (shouldKeepRunning && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]);

权限检查(必做)

打开Xcode项目的Signing & Capabilities标签,找到App Sandbox配置,确认勾选Network分类下的Outgoing Connections (Client)选项,避免网络请求被系统静默拦截。


内容的提问来源于stack exchange,提问作者Goasmad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 09:09:00