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

iOS中如何检测服务器及页面可用性?WKWebView与Reachability问题

搞定WKWebView检测域名解析失败/服务器宕机的问题

嘿,我看你遇到的问题挺典型的——用WKWebView时,碰到域名不存在或者服务器宕机的情况,didStartProvisionalNavigation触发后就没下文了,而且Reachability还误报说网络可达对吧?先给你揪出当前代码里的一个小错误,再给你两个靠谱的解决办法:

首先,你用Reachability的时候犯了个小错:reachabilityWithHostname:需要传的是纯主机名(比如chess.math.science.google.com),但你传的是完整的URL(带https://那种),这就导致Reachability的判断完全不准,日志里显示ReachableViaWiFi其实是无效的。赶紧改成这样:

Reachability* tinyReach = [Reachability reachabilityWithHostname:webView.URL.host];

接下来解决核心问题——WKWebView在域名挂了的时候没反应,我们可以从两个方向入手:

1. 用WKWebView的代理捕获导航失败

WKWebView其实有专门的代理方法处理导航启动阶段的错误,就是didFailProvisionalNavigation:,域名解析失败、服务器连不上、请求超时这些情况都会触发这个方法,你把它实现了就能像Chrome那样给用户提示了:

- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"加载出错啦: %@", error.localizedDescription);
    
    // 根据错误码给用户不同的提示
    switch (error.code) {
        case NSURLErrorCannotFindHost:
            // 找不到域名对应的IP,和Chrome的提示一致
            [self showErrorAlert:@"无法访问此网站,服务器IP地址无法找到"];
            break;
        case NSURLErrorCannotConnectToHost:
            // 服务器宕机或者拒绝连接
            [self showErrorAlert:@"无法连接到服务器,请稍后再试"];
            break;
        case NSURLErrorTimedOut:
            // 请求超时了
            [self showErrorAlert:@"请求超时,请检查你的网络连接"];
            break;
        default:
            [self showErrorAlert:@"加载失败: %@", error.localizedDescription];
            break;
    }
}

// 写个辅助方法弹提示框
- (void)showErrorAlert:(NSString *)message {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]];
    [self presentViewController:alert animated:YES completion:nil];
}

2. 提前发个轻量请求验证URL可用性

要是你想在WKWebView开始加载前就确认这个URL能不能用,可以提前发个HEAD请求(比GET请求轻,只拿响应头),这样能提前知道服务器状态,避免WKWebView卡住没反应:

- (void)checkURLBeforeLoad:(NSURL *)targetURL {
    NSURLRequest *checkRequest = [NSURLRequest requestWithURL:targetURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10.0];
    
    NSURLSessionDataTask *checkTask = [[NSURLSession sharedSession] dataTaskWithRequest:checkRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        // 切回主线程更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error) {
                // 请求失败,直接弹提示
                [self showErrorAlert:error.localizedDescription];
            } else {
                // 没问题,再让WKWebView加载
                [self.webView loadRequest:checkRequest];
            }
        });
    }];
    
    [checkTask resume];
}

用的时候就直接调用这个方法,而不是直接让WKWebView加载:

NSURL *urlToLoad = [NSURL URLWithString:@"https://chess.math.science.google.com"];
[self checkURLBeforeLoad:urlToLoad];

最后再啰嗦两句

Reachability只能帮你判断设备有没有连上网、能不能和某个主机建立TCP连接,但它管不了这个主机能不能正常返回HTTP内容,所以不能靠它来验证页面可用性。把上面的代理方法和提前请求的方式结合起来,就能覆盖大部分场景了——不管是域名解析失败、服务器宕机,还是404/500这些HTTP错误,都能处理到位。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:03:37