命令行模式下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
相关产品推荐
相关产品推荐

