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

iOS问题:使用Reachability检查网络后connectionDidFinishLoading未调用

解决Reachability检查后NSURLConnection代理方法不触发的问题

这个问题我之前也碰到过,大概率是Reachability回调线程和NSURLConnection依赖的RunLoop不匹配导致的,我给你拆解下核心原因和对应的解决办法:

核心原因分析

Reachability的状态变更回调block默认是在后台线程执行的,而旧版的NSURLConnection(你用的应该是代理模式)依赖创建它的线程的RunLoop才能触发代理方法(比如connectionDidFinishLoading:)。

如果在后台线程的block里直接创建NSURLConnection,block执行完后后台线程会立即退出,RunLoop也就停止了,自然无法触发代理回调;而直接在主线程调用单例时,主线程的RunLoop是一直运行的,所以代理方法能正常执行。


解决方案

方案1:切换到主线程执行网络请求(最简单可靠)

把调用DataManagement的网络请求代码放到主线程的dispatch队列里,利用主线程持续运行的RunLoop来保证代理方法触发:

// 你的Reachability监听代码
self.reachability = [Reachability reachabilityForInternetConnection];
[self.reachability setReachabilityStatusChangeBlock:^(Reachability *reachability) {
    NetworkStatus status = [reachability currentReachabilityStatus];
    if (status != NotReachable) {
        // 切换到主线程执行网络请求
        dispatch_async(dispatch_get_main_queue(), ^{
            [[DataManagement sharedInstance] callYourWebServiceMethod];
        });
    } else {
        NSLog(@"当前无网络连接");
    }
}];
[self.reachability startNotifier];

方案2:为NSURLConnection指定代理队列(不推荐,适用于必须在后台执行的场景)

如果一定要在后台线程执行请求,可以手动为NSURLConnection指定代理队列为主线程队列,这样代理方法会在主线程触发,不受后台线程生命周期影响:

// 在DataManagement的网络请求方法里修改
- (void)callYourWebServiceMethod {
    NSURLRequest *request = [self createWebServiceRequest]; // 你的请求创建逻辑
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    
    // 指定代理队列为主线程队列
    [connection setDelegateQueue:[NSOperationQueue mainQueue]];
    [connection start];
}

方案3:改用NSURLSession(推荐,长期解决方案)

NSURLConnection已经被苹果废弃,推荐使用NSURLSession,它的代理/ completionHandler不依赖线程RunLoop,不管在哪个线程调用都能正常触发回调:

// DataManagement里的网络请求方法改用NSURLSession
- (void)callYourWebServiceMethod {
    NSURL *url = [NSURL URLWithString:@"你的接口地址"];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (!error) {
            // 处理返回数据,若需更新UI记得切回主线程
            dispatch_async(dispatch_get_main_queue(), ^{
                // 解析数据/通知UI更新的逻辑
                NSLog(@"请求完成,数据长度:%lu", (unsigned long)data.length);
            });
        } else {
            NSLog(@"请求失败:%@", error.localizedDescription);
        }
    }];
    [task resume];
}

额外检查点

  1. 确认你的DataManagement单例实现是线程安全的,避免多次创建实例导致代理丢失:
+ (instancetype)sharedInstance {
    static DataManagement *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}
  1. 确认DataManagement已经遵守NSURLConnectionDataDelegate(如果用旧API)或NSURLSessionDataDelegate(如果用新API)协议。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 06:56:03