SDWebImage开源库详细使用指南

@SDWebImage提供一个UIImageView的类别以支持加载来自网络的远程图片。具有缓存管理、异步下载、同一个URL下载次数控制和优化等特征.

它提供了:

  • 添加网络图像和缓存管理到Cocoa Touch framework的UIImageView类别
  • 异步图像下载
  • An asynchronous memory + disk image caching with automatic cache expiration handling
  • 支持GIF动画
  • 支持WebP格式
  • 后台图像解压
  • 保证相同的url不会下载多次
  • 保证伪造的URL不会尝试一遍又一遍的下载
  • 保证主线程永远不会被阻塞
  • Performances!
  • 使用GCD和ARC

@SDWebImage的导入
1.https://github.com/rs/SDWebImage 下载SDWebImage开源包
2.将类包拖入工程,再导入MapKit.framework、ImageIO.framework两个框架
3.SDWebImage是支持ARC的,在MRC的工程中要注意,可参考MRC工程配置ARC
4.注意:SDWebImage 3.0不向后兼容2.0并且最低需要iOS 5.0 的版本,而且提供的方法多数是Blcok形式

@目前来说,主要用到了"UIImageView+WebCache.h",给出一个代码示例:

        它是UIImageView的一个类目,在要使用它的类中加入#import "UIImageView+WebCache.h",调用                setImageWithURL:placeholderImage:方法。从异步下载到缓存管理,一切都会为你处理。

@得到1个图片的url用SDWebImage缓存后的文件名

NSLog(@"%s__%d__|%@",__FUNCTION__,__LINE__,[[SDImageCache sharedImageCache] cachedFileNameForKey:@"http://c.hiphotos.baidu.com/image/w%3D2048/sign=396e9d640b23dd542173a068e531b2de/cc11728b4710b9123a8117fec1fdfc039245226a.jpg"]); 

对于不可见的ImageView取消图片的异步加载

不可见的ImageView加载图片的必要性大大降低,取消其加载任务可以加速其他图片的加载,也有助于减少资源占用。特别是在可以reuse的view中,一定要记得在prepareForReuse中取消掉当前imageView的图片加载。否则之前的加载任务,还会影响到当前reuse以前视图的imageView.

- (void)prepareForReuse
{
    [super prepareForReuse];
    [_imageView cancelCurrentImageLoad];
}

非必要情况下,避免使用SDWebImageManager

SDWebImageManager是UIImageView+WebCache的底层实现,通过SDWebImageManager可以实现异步的下载UIImage,官方也给出了示例代码。

SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:imageURL
                 options:0
                 progress:^(NSInteger receivedSize, NSInteger expectedSize)
                 {
                     // progression tracking code
                 }
                 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished)
                 {
                     if (image)
                     {
                         // do something with image
                     }
                 }];

但是SDWebImageManager并没有提供取消特定任务的方法,想要取消下载任务,会很麻烦。

如果只是希望使用SDWebImageManager实现pregress的效果显示加载进度。UIImageView+WebCache也提供了类似的方法。

[_imageView setImageWithURL:[NSURL URLWithString:url]
           placeholderImage:nil
                    options:0
                   progress:^(NSInteger receivedSize, NSInteger expectedSize) {
                       [weakSelf.downloadProgressLabel setText:[NSString stringWithFormat:@"%d%%",(int)(receivedSize*100/expectedSize)]];
                   }
                  completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
                      _downloadProgressLabel.hidden = YES;
                  }];

正如之前说的,使用[_imageView cancleCurrentImageLoad]可以取消这个ImageView的图片加载。


如何使用

API 文档地址 http://hackemist.com/SDWebImage/doc/

Using UIImageView+WebCache category with UITableView

       仅需引入 UIImageView+WebCache.h头文件,在UITableViewDataSource的方法tableView:cellForRowAtIndexPath:中调用setImageWithURL:placeholderImage:方法。从异步下载到缓存管理,一切都会为你处理。
#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 setImageWithURL: method to load the web image
    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    cell.textLabel.text = @"My Text";
    return cell;
}

Using blocks
       使用blocks,你将被告知下载进度,完成时是成功还是失败:
// Here we use the new provided setImageWithURL: method to load the web image
[cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
               placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                      completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {... completion code here ...}];

Using SDWebImageManager

      The SDWebImageManager is the class behind the UIImageView+WebCache category. It ties the asynchronous downloader with the image cache store. You can use this class directly to benefit from web image downloading with caching in another context than a UIView (ie: with Cocoa)

      下面是如何使用SDWebImageManager的代码:

SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadWithURL:imageURL
                 options:0
                 progress:^(NSUInteger receivedSize, long long expectedSize)
                 {
                     // progression tracking code
                 }
                 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType)
                 {
                     if (image)
                     {
                         // do something with image
                     }
                 }];


Using Asynchronous Image Downloader Independently
      也能够独立地使用异步图像下载:
[SDWebImageDownloader.sharedDownloader downloadImageWithURL:imageURL
                                                    options:0
                                                   progress:^(NSUInteger receivedSize, long long expectedSize)
                                                   {
                                                       // progression tracking code
                                                   }
                                                   completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished)
                                                   {
                                                       if (image && finished)
                                                       {
                                                           // do something with image
                                                       }
                                                   }];

Using Asynchronous Image Caching Independently
        也可以独立地使用基于异步的图像缓存存储。SDImageCache维护一个内存缓存和一个可选的磁盘缓存。磁盘高速缓存的写操作是异步进行的,所以它不会给UI增加不必要的延迟 。
        为了方便,SDImageCache类提供了一个单例,但是如果你想创建单独的缓存命名空间你也可以创建新的实例。
        你可以使用imageForKey:方法来查找缓存,如果返回为nil,说明当前图像不拥有缓存。因此你负责生成并缓存它。缓存键(cache key)是一个程序中图像缓存的唯一标识符,他通常是图像的url。
SDImageCache *imageCache = [SDImageCache.alloc initWithNamespace:@"myNamespace"];
[imageCache queryDiskCacheForKey:myCacheKey done:^(UIImage *image)
{
    // image is not nil if image was found
}];

       默认情况下,如果一个图像不能在内存缓存中找到,SDImageCache将会查找高速缓存。你可以调用替代的方法imageFromMemoryCacheForKey:来预防这种情况的发生。
        存储一个图像到缓存,你可以使用storeImage:forKey: 方法:
[[SDImageCache sharedImageCache] storeImage:myImage forKey:myCacheKey];

       默认情况下,图像将被存储在内存上的缓存以及磁盘上的缓存(异步)。如果你想只在内存中缓存,使用替代
方法storeImage:forKey:toDisk:,第三个参数为负数。

SDImageCache缓存图片

SDWebImage的cache有两个,硬盘cache和内存cache. 硬盘cache可以保存已下载的图片,避免再次下载;内存cache可以加速图片的加载速度,减少磁盘I/O.

既然有cache,肯定也有清除cache的方法,SDImageCache提供了清除硬盘cache和内存cache的方法,

[[SDImageCache sharedImageCache]clearDisk];
[[SDImageCache sharedImageCache]clearMemory];

一般情况下,我们并不需要手动的去清理cache,SDImageCache注册了相关的监听器,可以处理这些事宜。

// Subscribe to app events
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(clearMemory)
                                             name:UIApplicationDidReceiveMemoryWarningNotification
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(cleanDisk)
                                             name:UIApplicationWillTerminateNotification
                                           object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(backgroundCleanDisk)
                                             name:UIApplicationDidEnterBackgroundNotification
                                           object:nil];

上面的代码可以发现,当收到MemoryWarning时,SDImageCache会自动清空内存中的cache;当程序退出的时候,SDImageCache会clean硬盘上得cache,clean并不是clear,clean会将超出“保质期“的缓存图片删除掉。这个“保质期“可以通过maxCacheAge进行设定:

[SDImageCache sharedImageCache].maxCacheAge = 1 * 24 * 60 * 60; // 1 day

默认的“保质期”时间是:

static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week

通过SDImageCacheType判断图片来源

与SDImageCache相关的SDImageCacheType定义了加载的image的来源,下面是SDImageCacheType的定义。

typedef NS_ENUM(NSInteger, SDImageCacheType) {
    /**
     * The image wasn't available the SDWebImage caches, but was downloaded from the web.
     */
    SDImageCacheTypeNone,
    /**
     * The image was obtained from the disk cache.
     */
    SDImageCacheTypeDisk,
    /**
     * The image was obtained from the memory cache.
     */
    SDImageCacheTypeMemory
};

如果注意到之前的setImageWithURL:placeholderImage:options:progress:completed:方法,可以发现,completed的block参数包含一个cacheType,这个cacheType便是标记着当前image的来源。如果我们要对每个来自网络的图片进行淡入效果显示,可以这样写:

//other code
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
    _imageView.alpha = 0;
    if (cacheType == SDImageCacheTypeNone){
       [UIView animateWithDuration:0.3 animations:^{
            _imageView.alpha = 1;
        }];
    }
}];



Using cache key filter

        有时你也许不想使用图像URL作为缓存键,因为URL可能是动态的(i.e.: for access control purpose)。SDWebImageManager provides a way to set a cache key filter that takes the NSURL as input, and output a cache key NSString。


        下面的示例在应用程序的委托中设置一个过滤器,在使用它的缓存键之前将从URL中删除任何查询字符串(The following example sets a filter in the application delegate that will remove any query-string from the URL before to use it as a cache 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] autorelease];
        return [url absoluteString];
    };

    // Your app init code...
    return YES;
}

Using dynamic image size with UITableViewCell

      UITableView通过第一个单元格设置的图像决定图像的尺寸。如果您的远程图像没有图像占位符的大小相同,您可能会遇到奇怪的变形缩放问题。下面的文章给出了一个方法来解决这个问题:

http://www.wrichards.com/blog/2011/11/sdwebimage-fixed-width-cell-images/

Handle image refresh(控制图像刷新)

        默认情况下,SDWebImage确实非常积极的缓存。它忽略了所有类型的通过HTTP服务器返回的缓存控制头,并且没有时间限制地缓存返回的图像。这意味着你的图像url是永远不会改变的、指向图像的静态url。如果指向的图片发生了变化,那么url也会相应的跟着变化。

        如果你不控制你的图像服务器,当它的内容更新时你不能改变它的url。Facebook头像就是这种情况的例子。在这种情况下,你可以使用SDWebImageRefreshCached的标志。这将稍微降低性能,但将会考虑到HTTP缓存控制头:

[imageView setImageWithURL:[NSURL URLWithString:@"https://graph.facebook.com/olivier.poitrey/picture"]
          placeholderImage:[UIImage imageNamed:@"avatar-placeholder.png"]
                   options:SDWebImageRefreshCached];

SDWebImageDecoder的作用

SDWebImageDecoder只包含一个静态方法:

+ (UIImage *)decodedImageWithImage:(UIImage *)image;

该方法用来对已经加载的UIImage进行解码。

由于UIImage的imageWithData函数是每次画图的时候才将Data解压成ARGB的图像, 
所以在每次画图的时候,会有一个解压操作,这样效率很低,但是只有瞬时的内存需求。 
为了提高效率通过SDWebImageDecoder将包装在Data下的资源解压,然后画在另外一张图片上,这样这张新图片就不再需要重复解压了。 
这种做法是典型的空间换时间的做法。

上面是这段话来自摇滚诗人 http://www.cnblogs.com/biosli/archive/2012/07/21.html

显示GIF图片

SDWebImage显示Gif很占内存,这和SDWebImage对GIF的解码方式有关,相关代码如下:

+ (UIImage *)sd_animatedGIFWithData:(NSData *)data {
    if (!data) {
        return nil;
    }
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    size_t count = CGImageSourceGetCount(source);  
    UIImage *animatedImage;
    if (count <= 1) {
        animatedImage = [[UIImage alloc] initWithData:data];
    } else {
        NSMutableArray *images = [NSMutableArray array];
        NSTimeInterval duration = 0.0f;
        for (size_t i = 0; i < count; i++) {
            CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL);
            duration += [self frameDurationAtIndex:i source:source];
            [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]];
            CGImageRelease(image);
        }
        if (!duration) {
            duration = (1.0f / 10.0f) * count;
        }
        animatedImage = [UIImage animatedImageWithImages:images duration:duration];
    }
    CFRelease(source);
    return animatedImage;
}

这里的解码方式,单独对gif的每一帧进行解码,然后加入到animatedImage里面,这样,对于帧数很多的gif,则非常的占用内存。如果对GIF显示并不在乎GIF的显示的话,可以修改size_t count = CGImageSourceGetCount(source); 这段代码为sizt_t count = 1;这样GIF图片只会渲染第一帧,也就变成了一个静态图片展示,内存消耗也变得可以接受的范围。当然,如果要坚持使用GIF动画的话,也可以使用其他的开源项目,有些开源项目可以以占用内存非常少得方式显示GIF动画,比如说VVeboImage.


Add a progress indicator(添加进度指示)

查看这个类别: https://github.com/JJSaccolo/UIActivityIndicator-for-SDWebImage

SDWebImage中的一些参数:
*SDWebImageRetryFailed = 1<< 0,   默认选项,失败后重试
*SDWebImageLowPriority = 1<< 1,    使用低优先级
*SDWebImageCacheMemoryOnly = 1<< 2,   仅仅使用内存缓存
*SDWebImageProgressiveDownload = 1<< 3,   显示现在进度
*SDWebImageRefreshCached = 1<< 4,    刷新缓存
*SDWebImageContinueInBackground =1 << 5,   后台继续下载图像
*SDWebImageHandleCookies = 1<< 6,    处理Cookie
*SDWebImageAllowInvalidSSLCertificates= 1 << 7,    允许无效的SSL验证
*SDWebImageHighPriority = 1<< 8,     高优先级
*SDWebImageDelayPlaceholder = 1<< 9     延迟显示占位图片

Installation(安装)

有两种方式使用SDWebImage:
1.将文件全部拖入工程中;
2.将工程作为一个静态库拖入工程中。

Add the SDWebImage project to your project

  • Download and unzip the last version of the framework from the download page
  • Right-click on the project navigator and select "Add Files to "Your Project":
  • In the dialog, select SDWebImage.framework:
  • Check the "Copy items into destination group's folder (if needed)" checkbox

Add dependencies(添加依赖性)

  • In you application project app’s target settings, find the "Build Phases" section and open the "Link Binary With Libraries" block:
  • Click the "+" button again and select the "ImageIO.framework"(还缺一个“MapKit.framework”,readme中没提到), this is needed by the progressive download feature:

Add Linker Flag(添加链接标志)

     Open the "Build Settings" tab, in the "Linking" section, locate the "Other Linker Flags" setting and add the "-ObjC" flag:


参考:http://blog.csdn.net/shenjx1225/article/details/10444449

http://www.mzule.com/posts/SDWebImage_usage_experience.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值