SDWebImage是一个用于在iOS和macOS上异步加载图片的库,提供统一的API用于处理网络、缓存和动画。根据官方仓库的数据,该库被超过100,000个项目使用,支持GIF、WebP、SVG和渐进式加载。SDWebImage提供磁盘和内存的自动缓存,以及与UIKit和SwiftUI的集成。
要点
SDWebImage——用于在Apple平台(iOS, macOS, tvOS, watchOS)上异步加载图片的库。它为UIImageView提供了一个带有sd_setImage方法的类别,该方法一行代码即可从任何源加载、缓存和显示图片。
该库支持渐进式加载(图片随着字节的接收而显示)、动画图片(GIF, APNG)、变换(圆角、裁剪、添加水印)和自定义解码器。根据GitHub Stats,SDWebImage拥有超过25,000颗星,被包括Twitter、Pinterest和Instagram在内的大型应用使用。
架构基于组件链构建:Coder(解码)、Cache(存储)、Loader(网络)和Transformer(处理)。每个组件都是可替换的,允许将库适配到项目的特定要求。
SDWebImageManager——协调加载过程的中央组件。它接收URL,检查缓存,加载数据,将其解码为UIImage并传递给ImageView或完成处理器。管理器通过shared单例工作,可从应用的任何位置访问。
管理器依次检查Memory Cache(包含UIImage的NSDictionary),然后检查Disk Cache(文件系统)。如果数据缺失,通过NSURLSession执行网络请求。加载完成后,数据被解码,经过变换并保存在两个缓存中。整个过程在后台队列中执行,结果传递到主队列。
UIImageView+WebCache——Objective-C类别(可从Swift访问),添加了sd_setImage方法。该方法接收URL、占位符、选项(SDWebImageOptions)和完成块。类别通过sd_cancelCurrentImageLoad机制在表格单元格重复使用时自动取消先前的请求。
SDWebImage的架构分为多个具有明确责任区域的模块。每个类解决一个任务——从加载到显示。
SDWebImageManager——所有图片操作的门面。包含对ImageCache(SDImageCache)和ImageLoader(SDWebImageDownloader)的引用。通过SDWebImageManagerDelegate委托,可以拦截加载并修改URL或行为。
SDImageCache——两级缓存(内存+磁盘),使用唯一的命名空间初始化。Memory Cache存储具有可配置限制的UIImage(默认——直到系统内存警告)。Disk Cache在Library/Caches目录中存储数据,具有可配置的存储期限(默认为7天)。
SDWebImageDownloader——基于NSURLSession的HTTP客户端,支持标头、超时和重试。下载器将相同的请求合并为一个网络调用(去重)并在所有订阅者之间分发结果。
SDWebImage实现了具有确定性检查顺序的两级缓存:首先内存,然后磁盘。缓存键是不带查询参数的图片绝对URL或其MD5哈希。
| 级别 | 存储类型 | 内容 | 限制 |
|---|---|---|---|
| Memory Cache | NSCache (NSDictionary) | UIImage(解码后的位图) | 直到内存警告 |
| Disk Cache | 文件系统 | NSData (JPEG/PNG/WebP) | 7天TTL(可配置) |
| Auto Purge Cache | Memory + Disk | 框架的组合缓存 | 可配置的文件大小 |
当收到内存警告时,iOS通过UIApplicationDidReceiveMemoryWarningNotification通知SDImageCache,之后Memory Cache被完全清除。Disk Cache根据TTL或超过限制时清除,文件按最后访问日期排序。
用于手动管理缓存的方法:clearMemory、clearDisk、calculateSize。可以通过SDWebImageCacheMemoryOnly或SDWebImageAvoidAutoSetImage选项为特定请求禁用缓存。
SDWebImage提供多个用于加载图片的接口:从简单的UIImageView类别到具有自定义处理的高级管理器。
sd_setImage——在UIImageView中加载图片的主要方法。它接收URL、占位符和通过Options和Context传递的可选参数。所有完成处理器都在主线程中执行。
let imageView = UIImageView()
imageView.sd_setImage(
with: URL(string: "https://example.com/photo.jpg"),
placeholderImage: UIImage(named: "placeholder"),
options: [.progressiveLoad, .retryFailed],
context: [.imageThumbnailPixelSize : CGSize(width: 300, height: 300)]
)
该方法返回SDWebImageToken(一个操作),可以在需要时取消。在内部,sd_setImage调用SDWebImageManager.load,将ImageView作为目标传递以自动设置图片。
SDWebImage支持Transformer——一个带有单个方法transformedImage的协议。内置变换:圆形、圆角、应用颜色过滤器、调整大小。变换的组合使用&&运算符完成。
let transformer = SDImageResizingTransformer(
size: CGSize(width: 200, height: 200),
scaleMode: .aspectFill
)
let roundedTransformer = SDImageRoundCornerTransformer(
radius: 16,
corners: .allCorners,
borderWidth: 0
)
imageView.sd_setImage(
with: url,
placeholderImage: placeholder,
context: [.imageTransformer : transformer && roundedTransformer]
)
该库提供WebImage——一个用于SwiftUI的视图组件,支持占位符、进度指示器和错误处理。该组件自动订阅视图的生命周期并在消失时取消加载。
struct CachedImageView: View {
let url: URL
var body: some View {
WebImage(url: url) { phase in
if let image = phase.image {
image.resizable()
} else if phase.error {
Color.red
} else {
ProgressView()
}
}
}
}
SDWebImage通过SDImageTransformer协议提供灵活的图片变换系统。变换在解码之后但在缓存之前应用——变换结果以新键存储在磁盘上,消除了在后续请求中重复应用的需要。
内置变换包括:SDImageResizingTransformer(带模式调整大小)、SDImageRoundCornerTransformer(带可选边框的圆角)、SDImageFlipTransformer(镜像翻转)和SDImageFilterTransformer(CoreImage滤镜)。使用&&运算符组合,创建处理链。
对于自定义变换,只需实现带有transformedImageWithImage:forKey:方法的SDImageTransformer协议。变换键自动添加到缓存键中,防止同一图片不同版本之间的冲突。
在iOS平台上,SDWebImage的主要竞争对手是Kingfisher(纯Swift)和Nuke。SDWebImage和Kingfisher之间的选择通常取决于项目的语言和所需的功能。
| 特性 | SDWebImage | Kingfisher |
|---|---|---|
| 语言 | Objective-C + Swift API | Swift (100%) |
| SwiftUI | WebImage View | KFImage View |
| GIF | 是(内置) | 是(内置) |
| WebP | 是(插件) | 是(内置) |
| 渐进式加载 | 是(带插件) | 是 |
| 框架大小 | ~1.2 MB | ~900 KB |
| 缓存 | Memory + Disk | Memory + Disk |
| CocoaPods支持 | 是 | 是 |
SDWebImage仍然是Objective-C项目或混合项目的首选。Kingfisher由于类型安全性和原生Swift语法更适合纯Swift项目。两个库具有相似的缓存架构和速度。
连接SDWebImage通过Swift Package Manager、CocoaPods或Carthage完成。该库分为模块:主模块(SDWebImage)、Coder(额外格式)和MapKit(用于MKAnnotationView)。
// Swift Package Manager (Package.swift)
dependencies: [
.package(
url: "https://github.com/SDWebImage/SDWebImage.git",
from: "5.19.0"
)
]
// CocoaPods (Podfile)
pod 'SDWebImage', '~> 5.19.0'
// WebP和SVG的插件:
pod 'SDWebImageWebPCoder'
pod 'SDWebImageSVGCoder'
安装后,库即可使用,无需额外配置。要自定义缓存,创建一个具有唯一命名空间的SDImageCache实例,在初始化时传递给SDWebImageManager。全局配置通过SDWebImageManager.shared完成。
// 自定义缓存
let config = SDImageCacheConfig()
config.maxDiskAge = 14 * 86400 // 14天而不是7天
config.maxDiskSize = 500 * 1024 * 1024 // 500 MB
config.shouldCacheImagesInMemory = .true
let cache = SDImageCache(
namespace: "custom",
diskCacheDirectory: FileManager.default.urls(
for: .cachesDirectory,
in: .userDomainMask
).first?.appendingPathComponent("custom_cache"),
config: config
)
SDWebImageManager.sharedImageCache = cache
常见问题
SDWebImage——用于在iOS和macOS上异步加载图片的库。它解决了从网络加载图片的缓存、解码、变换和显示任务,将开发者从手动线程和内存管理中解放出来。
在cellForRowAt方法中使用带URL和占位符的sd_setImage。该库在单元格重复使用时自动取消先前的请求。为了平滑滚动,指定.progressiveLoad选项并通过上下文配置缩略图大小。
SDWebImage用Objective-C编写,带有Swift包装器,Kingfisher用纯Swift编写。SDWebImage拥有更广泛的插件生态系统(WebP、SVG、MapKit)。Kingfisher提供更好的类型安全性和与Swift Concurrency的集成。
通过CocoaPods或SPM安装SDWebImageWebPCoder插件。在AppDelegate中调用SDImageWebPCoder.shared注册解码器。注册后,库自动检测格式并解码WebP。
调用SDImageCache.shared.clearMemory()清除内存缓存,调用SDImageCache.shared.clearDisk()清除磁盘缓存。要只清除过期的文件,使用带TTL检查的clearDisk(completion:)。calculateSizeWithCompletionBlock方法返回当前缓存大小。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。