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

SDWebImage加载图片报Error code=-1003/Err(-65554)问题求助

针对SDWebImage DNS加载失败(Error -1003/Err-65554)的解决方案

你遇到的这个DNS解析失败问题在iOS网络请求里挺常见的,尤其是在WiFi网络不稳定或者DNS缓存异常的场景下。下面给你几个适合上线环境的解决方案,不用依赖VPN或者手动切换网络:

1. 利用SDWebImage自带的重试机制优化

SDWebImage其实有内置的失败重试能力,只是默认没开启或者重试次数不够。你可以通过两个方式配置:

方式一:全局设置下载器重试次数

在App启动的时候(比如application:didFinishLaunchingWithOptions:里)配置全局的下载器重试次数,这样所有图片请求都会生效:

SDWebImageDownloader *sharedDownloader = [SDWebImageDownloader sharedDownloader];
sharedDownloader.maxRetryCount = 3; // 设置失败后重试3次,你可以根据需求调整

方式二:单个请求启用重试选项

在加载图片的代码里,把SDWebImageRetryFailed选项加入到options中,这样这个请求失败时会自动重试:

[cell.i_imageView sd_setImageWithURL:[NSURL URLWithString:item.imageUrl]
                  placeholderImage:[UIImage imageNamed:@"no-image"]
                           options:SDWebImageRefreshCached | SDWebImageRetryFailed
                         completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
    if(!image) NSLog(@"image not loaded %@", error.description);
}];

这个选项会让SDWebImage在遇到DNS错误这类网络失败时自动重试,配合全局的重试次数设置,能大大降低加载失败的概率。

2. 自定义NSURLSessionConfiguration优化网络请求

iOS 11之后,NSURLSessionConfiguration新增了waitsForConnectivity属性,它能让请求在网络不可用时等待,而不是立刻返回失败。同时你还可以延长超时时间,给DNS解析更多时间:

// 创建自定义的Session配置
NSURLSessionConfiguration *customConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
customConfig.timeoutIntervalForResource = 30; // 把资源超时时间设为30秒,默认是60秒,你可以按需调整
if (@available(iOS 11.0, *)) {
    customConfig.waitsForConnectivity = YES; // 开启等待网络连接的能力
}

// 用这个配置初始化SDWebImageManager
SDWebImageManager *customManager = [[SDWebImageManager alloc] initWithCache:[SDImageCache sharedImageCache]
                                                                   downloader:[[SDWebImageDownloader alloc] initWithSessionConfiguration:customConfig]];

// 使用自定义manager加载图片
[customManager loadImageWithURL:[NSURL URLWithString:item.imageUrl]
                        options:SDWebImageRefreshCached
                       progress:nil
                      completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
    if (image) {
        cell.i_imageView.image = image;
    } else {
        NSLog(@"image not loaded %@", error.description);
    }
}];

这个配置的好处是,当WiFi网络DNS解析失败但网络还在连接过程中,或者临时断网后恢复,请求会自动继续,不需要你自己写重试逻辑。

3. 针对特定URL强制使用蜂窝网络(iOS 13+)

如果你的场景中,蜂窝网络的DNS解析更可靠,可以针对失败的请求切换到蜂窝网络的Session来重试。iOS 13之后,NSURLSessionConfiguration提供了控制网络类型的属性:

// 先监听当前网络状态,或者在请求失败后判断错误类型
[cell.i_imageView sd_setImageWithURL:[NSURL URLWithString:item.imageUrl]
                  placeholderImage:[UIImage imageNamed:@"no-image"]
                           options:SDWebImageRefreshCached
                         completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
    if (!image && error.code == -1003) { // 确认是DNS错误
        // 创建仅允许蜂窝网络的Session配置
        NSURLSessionConfiguration *cellularConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
        cellularConfig.allowsCellularAccess = YES;
        cellularConfig.allowsExpensiveNetworkAccess = YES; // 允许使用蜂窝这类"昂贵"网络
        cellularConfig.allowsConstrainedNetworkAccess = YES; // 如果系统开启低数据模式也允许使用

        // 用这个配置创建下载器并重试请求
        SDWebImageDownloader *cellularDownloader = [[SDWebImageDownloader alloc] initWithSessionConfiguration:cellularConfig];
        [cellularDownloader downloadImageWithURL:[NSURL URLWithString:item.imageUrl]
                                         options:SDWebImageRefreshCached
                                        progress:nil
                                       completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
            if (image) {
                cell.i_imageView.image = image;
            }
        }];
    }
}];

这个方法需要注意用户的蜂窝数据权限,不过一般App默认都有蜂窝数据权限,而且只有在WiFi请求失败时才会触发,不会影响正常场景。

4. 自定义DNS解析绕过系统DNS

如果上述方法都无法解决,你可以自己做DNS解析,拿到域名对应的IP后,直接用IP构造请求并设置Host头,绕过系统的DNS解析:

// 异步解析域名(避免阻塞主线程)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSString *domain = [NSURL URLWithString:item.imageUrl].host;
    struct addrinfo hints = {0}, *res;
    hints.ai_family = AF_UNSPEC; // 支持IPv4和IPv6
    hints.ai_socktype = SOCK_STREAM;
    
    int result = getaddrinfo([domain UTF8String], NULL, &hints, &res);
    if (result == 0 && res) {
        char ipBuffer[INET6_ADDRSTRLEN];
        // 提取IP地址
        if (res->ai_family == AF_INET) {
            struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr;
            inet_ntop(AF_INET, &ipv4->sin_addr, ipBuffer, sizeof(ipBuffer));
        } else {
            struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)res->ai_addr;
            inet_ntop(AF_INET6, &ipv6->sin6_addr, ipBuffer, sizeof(ipBuffer));
        }
        freeaddrinfo(res);
        
        NSString *ipStr = [NSString stringWithUTF8String:ipBuffer];
        // 构造用IP替换域名的URL
        NSString *ipBasedUrlStr = [item.imageUrl stringByReplacingOccurrencesOfString:domain withString:ipStr];
        NSURL *ipURL = [NSURL URLWithString:ipBasedUrlStr];
        
        // 构造请求并设置Host头(必须,否则服务器无法识别域名)
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:ipURL];
        [request setValue:domain forHTTPHeaderField:@"Host"];
        
        // 回到主线程加载图片
        dispatch_async(dispatch_get_main_queue(), ^{
            [cell.i_imageView sd_setImageWithURLRequest:request
                                      placeholderImage:[UIImage imageNamed:@"no-image"]
                                               options:SDWebImageRefreshCached
                                              completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
                if (!image) NSLog(@"image not loaded %@", error.description);
            }];
        });
    }
});

这个方法需要处理DNS解析的异常情况,比如解析失败的场景,但能彻底绕过系统DNS的问题,适合DNS解析问题比较顽固的情况。


优先推荐前两种方案,因为它们利用SDWebImage和系统API的原生能力,稳定性高且代码侵入性小。如果你的用户经常遇到WiFi DNS问题,第三种方案可以作为补充。第四种方案则是最后的兜底选项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:05:31