SDWebImage 实战指南:从 UIImageView 分类到下载器、缓存与 Manager 的完整用法
【免费下载链接】SDWebImageAsynchronous image downloader with cache support as a UIImageView category项目地址: https://gitcode.com/GitHub_Trending/sd/SDWebImage
本指南以 SDWebImage 官方文档 Docs/HowToUse.md 为主线,系统讲解在 iOS/macOS 应用中接入 SDWebImage 的全部核心用法:在UITableView中通过UIImageView+WebCache分类加载网络图片、利用 blocks 感知下载进度与完成回调、直接使用SDWebImageManager编排「缓存查询 + 异步下载」、独立使用SDWebImageDownloader与SDImageCache,以及通过 cache key filter 自定义缓存键。读完本文,你将能够熟练替换图片加载的各个环节,并在非UIView场景(如 Cocoa 桌面应用)中复用 SDWebImage 的下载与缓存能力。
一、环境与组件概览
SDWebImage 是一个「异步图片下载 + 缓存」库,其核心架构由三层组成(对应仓库源码目录 SDWebImage/Core):
| 组件 | 头文件 | 职责 |
|---|---|---|
| UI 层分类 | UIImageView+WebCache.h | 面向UIImageView/UIButton等视图的一行式 API |
| 编排层 | SDWebImageManager.h | 串联缓存查询与下载,生成统一缓存键 |
| 执行层 | SDWebImageDownloader.h 与 SDImageCache.h | 分别负责异步网络下载与内存/磁盘两级缓存 |
从源码结构看,SDWebImageManager聚合了id<SDImageCache>(默认SDImageCache)与id<SDImageLoader>(默认SDWebImageDownloader)两个协议对象,并在每次请求中依次执行「查缓存 → 未命中则下载 → 写入缓存」的流水线。下面按官方文档的顺序逐层展开。
二、在 UITableView 中使用UIImageView+WebCache分类
2.1 核心用法(Objective-C)
在tableView:cellForRowAtIndexPath:中导入头文件并调用sd_setImageWithURL:placeholderImage:,异步下载、解码、缓存与自动回调全部由库内部处理,无需手动管理NSOperation或缓存逻辑:
#import <SDWebImage/UIImageView+WebCache.h> - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *MyIdentifier = @"MyIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease]; } // 异步加载网络图片,placeholder 在加载期间占位 [cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"]]; cell.textLabel.text = @"My Text"; return cell; }UIImageView (WebCache)分类在 UIImageView+WebCache.h 中提供了从sd_setImageWithURL:到带options:context:progress:completed:的完整方法族,sd_setImageWithURL:placeholderImage:是最常用的简化版本。官方建议在 cell 复用场景务必提供 placeholder 图片,否则 cell 首次显示会出现空图闪烁。
2.2 Swift 等价写法
Swift 侧直接import SDWebImage,API 签名通过NS_REFINED_FOR_SWIFT进行了 Swift 化适配(见 UIImageView+WebCache.h):
import SDWebImage func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { static let myIdentifier = "MyIdentifier" let cell = tableView.dequeueReusableCellWithIdentifier(myIdentifier, forIndexPath: indexPath) as UITableViewCell cell.imageView.sd_setImageWithURL(imageUrl, placeholderImage: placeholderImage) return cell }注意:
dequeueReusableCellWithIdentifier:forIndexPath:要求 cell 已注册到 storyboard/collectionView,示例仅演示加载逻辑本身。
2.3 真实 Demo 中的进阶用法
仓库自带的 Examples/SDWebImage Demo/MasterViewController.m 展示了更贴近生产的组合:cell 上挂载了fadeTransition淡入动画与grayIndicator加载指示器,并通过 context 传入缩略图像素尺寸,配合progress:回调与SDAnimatedImageView使用:
__weak SDAnimatedImageView *imageView = cell.customImageView; [imageView sd_setImageWithURL:[NSURL URLWithString:self.objects[indexPath.row]] placeholderImage:placeholderImage options:0 context:@{SDWebImageContextImageThumbnailPixelSize : @(CGSizeMake(180, 120))} progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { // 通过操作 token 读取下载进度等附加信息 SDWebImageCombinedOperation *operation = [imageView sd_imageLoadOperationForKey:imageView.sd_latestOperationKey]; SDWebImageDownloadToken *token = operation.loaderOperation; if (@available(iOS 10.0, *)) { // 使用 token.response 或 token.metrics 统计网络指标 } }];三、使用 blocks 感知进度与结果
当需要获知下载进度或成功/失败结果时,可换用带 block 的重载方法。completed:block 会收到四个参数:最终图片、错误对象、缓存来源类型(SDImageCacheType)与原始 URL:
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { ... completion code here ... }];重要约定:如果图片请求在完成前被取消(例如 cell 被复用、滚动离开屏幕触发了自动取消),那么无论成功还是失败回调都不会被调用。这一取消行为由 UIView+WebCacheOperation.m 维护的操作映射保证——每次新的sd_setImageWithURL:调用都会先取消上一次未完成的操作。若业务上不希望自动取消,可以在 options 中传入SDWebImageAvoidAutoCancelImage(定义见 SDWebImageDefine.h)。
此外还可组合options:与progress:使用,progress block 在后台队列执行并持续回调已接收/预期字节数;options 的完整取值枚举SDWebImageOptions同样定义在 SDWebImageDefine.h,常见的有:
| Option | 说明 |
|---|---|
SDWebImageRetryFailed | 失败 URL 默认会被加入黑名单不再重试,此选项关闭该行为 |
SDWebImageProgressiveLoad | 渐进式加载,边下载边显示(类似浏览器) |
SDWebImageRefreshCached | 即使已缓存也尊重 HTTP 缓存策略重新校验 |
SDWebImageHighPriority/SDWebImageLowPriority | 调整下载在队列中的优先级 |
SDWebImageFromCacheOnly/SDWebImageFromLoaderOnly | 仅查询缓存 / 仅走加载器,跳过另一阶段 |
四、直接使用 SDWebImageManager 编排下载与缓存
SDWebImageManager是UIImageView(WebCache)分类背后的核心类,它将异步下载器(SDWebImageDownloader)与图片缓存(SDImageCache)绑定在一起(见 SDWebImageManager.h 的类注释)。在非UIView场景(例如 Cocoa 桌面应用、自定义数据处理管道)下,可直接使用它获得「带缓存的网络图片」能力。
SDWebImageManager *manager = [SDWebImageManager sharedManager]; [manager loadImageWithURL:imageURL options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) { // progression tracking code } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { if (image) { // do something with image } }];loadImageWithURL:options:progress:completed:的完整签名(见 SDWebImageManager.h)说明如下:
completedblock 必需,内部完成回调类型为SDInternalCompletionBlock:image(请求图片,错误时为 nil)、data(NSData 表示)、error、cacheType(SDImageCacheType枚举:内存/磁盘/网络命中)、finished(配合渐进式加载,NO 表示部分图片)、imageURL。- 返回值是
SDWebImageCombinedOperation(定义于 SDWebImageManager.h),它聚合了 cache 查询操作与 loader 下载操作,可调用cancel一次性取消整个流水线。 - 方法内部首先通过
cacheKeyForURL:计算缓存键,然后按「内存缓存 → 磁盘缓存 → 网络下载」的顺序处理,命中缓存则直接回调,未命中才交给imageLoader。
4.1 关于内存缓存与图片数据的注意点
文档明确提示:当图片命中内存缓存时,默认不会附带NSData。若你需要拿到图片原始数据,必须在 options 中传入SDWebImageQueryDataWhenInMemory(即SDWebImageQueryMemoryData,定义见 SDWebImageDefine.h),并视需要组合SDWebImageQueryMemoryDataSync实现同步查询。这是 SDWebImage 在内存缓存上默认「只存解码后的 UIImage、不存 NSData」以节约内存的实现决策。
4.2 自定义 Manager 的三种方式
除sharedManager单例外,SDWebImageManager.h 还提供了两种自定义入口:
// 方式一:指定自定义 cache 与 loader 创建新实例 SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:myCache loader:myLoader]; // 方式二:为后续创建的 manager 设定全局默认组件(类属性) SDWebImageManager.defaultImageCache = myCache; SDWebImageManager.defaultImageLoader = myLoader;此外,通过SDWebImageContextImageCache/SDWebImageContextImageLoader等 context 选项(见 SDWebImageDefine.h),可以在单次请求级别覆盖 cache 与 loader,无需重建 manager。
五、独立使用异步图片下载器 SDWebImageDownloader
如果只想复用「下载」能力而不要缓存(例如下载后自行处理数据),可以直接使用SDWebImageDownloader:
SDWebImageDownloader *downloader = [SDWebImageDownloader sharedDownloader]; [downloader downloadImageWithURL:imageURL options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) { // progression tracking code } completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { if (image && finished) { // do something with image } }];该方法(完整签名见 SDWebImageDownloader.h)返回一个SDWebImageDownloadToken(SDWebImageDownloader.h),可调用其cancel取消下载,并可读取url、request、response与网络指标metrics。注意区分两点:
finished参数:不使用渐进式加载时总是 YES;使用SDWebImageDownloaderProgressiveLoad时会在下载中多次回调(图片为部分数据),最后一次才为 YES。- downloader 层面的 options 是
SDWebImageDownloaderOptions(SDWebImageDownloader.h),与 UI 层的SDWebImageOptions是两套独立枚举,常见如SDWebImageDownloaderContinueInBackground(后台续传)、SDWebImageDownloaderHandleCookies(跟随 Cookie)、SDWebImageDownloaderAllowInvalidSSLCertificates(仅测试用)等。
SDWebImageDownloader还支持通过requestModifier、responseModifier、decryptor三个钩子分别改造请求、响应与解密数据(SDWebImageDownloader.h),并可通过setValue:forHTTPHeaderField:为每个请求附加 HTTP 头。
六、独立使用异步图片缓存 SDImageCache
SDImageCache维护一个内存缓存(memory cache)与一个可选的磁盘缓存(disk cache),磁盘写入操作全部异步执行,因此不会给 UI 线程增加额外延迟(见 SDImageCache.h)。它提供sharedImageCache单例,也允许创建带独立 namespace 的自有实例,以隔离不同业务的缓存空间:
SDImageCache *imageCache = [[SDImageCache alloc] initWithNamespace:@"myNamespace"]; [imageCache queryDiskCacheForKey:myCacheKey done:^(UIImage *image) { // image is not nil if image was found }];初始化方法initWithNamespace:会在默认缓存目录下创建($directory/$namespace)子目录(SDImageCache.h);若需要自定义根目录,可改用initWithNamespace:diskCacheDirectory:或initWithNamespace:diskCacheDirectory:config:。
6.1 查询缓存:key 的语义与查询顺序
- 调用
queryDiskCacheForKey:done:查询。若回调返回 nil,表示缓存中不存在该图,此时应由调用方负责生成图片并写入缓存。 - 缓存 key 是应用内唯一的图片标识,通常直接使用图片的绝对 URL(
absoluteString)。 - 查询顺序:默认先查内存缓存,未命中再查磁盘缓存。若只想查内存,改用同步方法
imageFromMemoryCacheForKey::
UIImage *memoryImage = [imageCache imageFromMemoryCacheForKey:myCacheKey];从当前版本源码看,queryDiskCacheForKey:done:已演进为queryCacheOperationForKey:done:(返回可取消的SDImageCacheToken),并支持通过SDImageCacheOptions控制查询行为,例如SDImageCacheQueryMemoryData(强制同时返回内存中的 NSData)、SDImageCacheQueryMemoryDataSync/SDImageCacheQueryDiskDataSync(同步查询)、SDImageCacheScaleDownLargeImages(大图降采样)等(SDImageCache.h)。
6.2 写入缓存:内存 + 磁盘两种策略
使用storeImage:forKey:completion:存储图片:
[[SDImageCache sharedImageCache] storeImage:myImage forKey:myCacheKey completion:^{ // image stored }];- 默认行为:图片会同时写入内存缓存与磁盘缓存(磁盘为异步写入)。
- 若只想存内存,使用带第三个参数的变体
storeImage:forKey:toDisk:completion:,并将toDisk传 NO(文档中的「negative third argument」即此含义): - 若只写磁盘,可调用
storeImageDataToDisk:forKey:直接存储 NSData,或使用storeImage:imageData:forKey:toDisk:completion:显式提供原始数据(服务端原样数据可避免二次编码、保留画质)。
SDImageCache.h 还提供removeImageForKey:、clearMemory、clearDiskOnCompletion:、deleteOldFilesWithCompletionBlock:、calculateSizeWithCompletionBlock:等维护接口,便于业务侧管理缓存生命周期。缓存行为可通过SDImageCacheConfig调整(SDImageCacheConfig.h):如maxDiskAge(默认 1 周)、maxDiskSize/maxMemoryCost(0 表示不限制)、shouldDisableiCloud(默认 YES,禁用 iCloud 备份)、shouldCacheImagesInMemory、shouldUseWeakMemoryCache等。
仓库测试 Tests/Tests/SDImageCacheTests.m 覆盖了这些路径:test06InsertionOfImage验证storeImage:forKey:后内存缓存同步命中;test08InsertionOfImageOnlyInMemory验证toDisk:NO时磁盘不落盘、clearMemory后内存不可见,可作为理解上述行为差异的实证。
七、使用 cache key filter 自定义缓存键
有时图片 URL 包含动态部分(例如带访问控制参数的 query-string),导致同一张图每次 URL 都不同、缓存大量失效。SDWebImageManager提供 cache key filter:输入NSURL,输出缓存键NSString。
下面的例子在应用代理中设置 filter,将 URL 的 query-string 移除后再作为缓存键——去掉?token=xxx这类动态参数,让同一资源复用同一份缓存:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { SDWebImageManager.sharedManager.cacheKeyFilter = ^(NSURL *url) { url = [[NSURL alloc] initWithScheme:url.scheme host:url.host path:url.path]; return [url absoluteString]; }; // Your app init code... return YES; }关于该 API 的源码细节:
- 现代写法推荐使用
SDWebImageCacheKeyFilter类包装 block:[SDWebImageCacheKeyFilter cacheKeyFilterWithBlock:...],它实现了SDWebImageCacheKeyFilter协议(- cacheKeyForURL:),便于 Swift 使用(见 SDWebImageCacheKeyFilter.h)。 - filter 的产出将影响
SDWebImageManager每次访问缓存时所使用的 key(SDWebImageManager.h)。 - 仓库测试 Tests/Tests/SDWebImageManagerTests.m 的
test09ThatCacheKeyFilterWork展示了完整验证流程:为 manager 设置 filter 后加载图片,再断言图片以自定义 key 出现在内存缓存中,可作为集成测试模板。
八、常见问题与最佳实践
- 务必使用 placeholder:cell 复用场景下未提供占位图会出现空白闪烁;自定义 cell 时还可搭配
sd_imageTransition(淡入动画)与sd_imageIndicator(加载指示器),参见 Examples/SDWebImage Demo/MasterViewController.m。 - 理解取消语义:
completed:block 在请求被取消时不会回调,因此不要在 block 内做必须执行的清理逻辑;需要在 cell 复用时手动取消旧请求可用sd_cancelCurrentImageLoad(UIImageView+WebCache.h)。 - 缓存键设计决定缓存命中率:URL 带签名/时间戳等动态参数时,通过 cache key filter 归一化缓存键;注意 filter 是全局生效的,会影响所有经过该 manager 的请求。
- 内存缓存默认无 NSData:需要原始数据(如二次加工、上传)时记得传
SDWebImageQueryMemoryData。 - 按需拆分层级:仅展示图片用 UI 分类;非视图场景用
SDWebImageManager;只需下载用SDWebImageDownloader;只需缓存用SDImageCache,各层均可独立复用。 - 缓存目录与 namespace:多业务模块使用不同 namespace 隔离磁盘缓存,避免 key 冲突与互相清理。
参考资料
- 官方使用指南:Docs/HowToUse.md
- UI 分类头文件:UIImageView+WebCache.h、UIView+WebCache.h
- 编排层:SDWebImageManager.h、SDWebImageCacheKeyFilter.h
- 执行层:SDWebImageDownloader.h、SDImageCache.h、SDImageCacheConfig.h
- Options 枚举与 context 选项:SDWebImageDefine.h
- 真实 Demo:Examples/SDWebImage Demo/MasterViewController.m
- 测试用例:Tests/Tests/SDWebImageManagerTests.m、Tests/Tests/SDImageCacheTests.m
【免费下载链接】SDWebImageAsynchronous image downloader with cache support as a UIImageView category项目地址: https://gitcode.com/GitHub_Trending/sd/SDWebImage
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考