最近正在自学iOS,看到网上有项目用SDWebImage,便找来文档看看,顺便记录一下,也方便大家阅读(官方文档地址: http://cocoadocs.org/docsets/SDWebImage/3.7.5/ 以下是翻译内容)。
Web Image
SDWebImage提供了一个UIImageView的分类来支持获取远程图片。这个库提供了如下功能:
1. 提供UIImageView的一个分类用以支持对Cocoa Touch framework添加网络图片以及管理、缓存图片。
2. 支持异步图片下载
3. 支持内存+硬盘级的图片缓存,并且自动处理缓存过期情况
4. 支持GIF
5. 支持WebP 格式
6. 支持后台解码图片
7. 保证同一个URL的图片不会被多次重复下载
8. 保证不会多次尝试访问一个失效或者错误的URL
9. 保证主线程不会被卡住
10. 性能优秀
11. 使用GCD和ARC
12. 支持Arm64
注意:3.0版本的SDWebImage不能完全兼容2.0版本,并且3.0版本需要iOS版本5.1.1以上。如果你需要在iOS 5.0以下版本开发,请使用2.0版本的SDWebImage
在UITableview中使用UIImageView+WebCache分类
只需要导入UIImageView+WebCache.h头文件,然后在tableView:cellForRowAtIndexPath: 中调用sd_setImageWithURL:placeholder:方法,SDWebImage将会帮你处理下载和缓存的所有工作。
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];
}
// Here we use the new provided sd_setImageWithURL: method to load the web image
[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;
}
使用Blocks
你可以使用blocks来通知你的程序图片下载进度以及图片下载完成与否。这里我们使用sd_setImageWithURL:方法来加载网络图片
[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 ...
}];
注意,如果在图片下载完成之前取消了图片下载,success或者failure block不会被调用
使用SDWebImageManager
SDWebImageManager是在UIImageView+WebCache分类背后实现很多功能的类,这个类会异步下载图片到缓存中。你可以直接使用这个类来缓存图片,而不用在UIView类中调用(照我的理解就是不用在初始化UI的时候下载图片,而是后台直接先把图片下载下来供以后使用)。下面举个栗子:
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL: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
}
}];
单独使用异步图片下载器
单独调用异步图片下载器也是可以的,请看代码:
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
}
}];
单独使用异步图片缓存
单独调用基于异步操作的图片缓存也是可以的。SDImageCache 类中维护着一个内存缓存和一个可选的硬盘缓存(也就是内存和外存)。硬盘缓存的写操作是异步的,不会对UI刷新增加不必要的延迟。
SDImageCache类提供一个单例,但是如果你想创建一个与默认实例不同名字空间的缓存,你也可以创建自己的实例。
你可以调用 queryDiskCacheForKey:done: 方法从缓存中寻找图片。如果该方法返回nil,说明要寻找的图片并没有缓存下来,那么你有必要自己调用方法来缓存它。缓存标识key是全局唯一的,通常来说默认是图片的绝对URL。
SDImageCache *imageCache = [[SDImageCache alloc] initWithNamespace:@"myNamespace"];
[imageCache queryDiskCacheForKey:myCacheKey done:^(UIImage *image) {
// image is not nil if image was found
}];
默认情况下,SDImageCache将会先在memory缓存中寻找图片,如果没找到,会去disk缓存中寻找。如果你只想在memory缓存中寻找,可以调用imageFromMemoryCacheForKey:方法。
要将图片添加到缓存里,你可以调用 storeImage:forKey: 方法
[[SDImageCache sharedImageCache] storeImage:myImage forKey:myCacheKey];
默认情况下,图片会同时被缓存到memory和disk缓存中(当然是异步的哈)。如果你只想缓存到memeory中,调用storeImage:forKey:toDisk: (原文为:use the alternative method storeImage:forKey:toDisk: with a negative third argument,是说第三个参数就填个无效的值?)
使用缓存key过滤器
有时候可能你不想用图片的URL作为缓存的key,因为有时候URL是动态的。SDWebImageManager提供一个方法来设置一个缓存key过滤器,这个过滤器接收NSURL作为输入,然后生成一个NSString的缓存key。
下面的栗子是在APPDelegate中设置了一个过滤器,这个过滤器会去除掉URL中的查询字符串(query-string,也就是URL问好后面的那段),然后将其作为缓存key
- (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;
}
常见问题
在UITableViewCell中使用动态图片尺寸
UITableView中的图片尺寸被cell中的第一个image set所决定。如果你的网络图片大小与placeholder图片的不一致,下面的链接可能帮到你:
http://www.wrichards.com/blog/2011/11/sdwebimage-fixed-width-cell-images/ (这个网站打不开啊。。)
处理图片刷新
SDWebImage默认情况下缓存图片非常快。它不鸟所有HTTP服务器返回来的缓存控制头,直接缓存图片。这暗示着图片的URLs是静态的,不会改变。如果URL指向的图片改变了,URL也应该跟着改变。
如果你不能控制图片服务器,当图片发生变化时,可能你就不能修改图片的URL。这种情况就像Facebook的avatar URLs。这种情况下,你可以使用SDWebImageRefresheCached标识。这会稍微减缓缓存性能,从而遵循HTTP返回的HTTP caching control headers
[imageView sd_setImageWithURL:[NSURL URLWithString:@"https://graph.facebook.com/olivier.poitrey/picture"]
placeholderImage:[UIImage imageNamed:@"avatar-placeholder.png"]
options:SDWebImageRefreshCached];