2018-06-06 SDWebImage深度学习
SDWebImage
1.它是iOS图片加载框架
它支持从网络中下载且缓存图片,并设置图片到对应的UIImageView控件或者UIButton控件。在项目中使用SDWebImage来管理图片加载相关操作可以极大地提高开发效率,让我们更加专注于业务逻辑实现。
实现原理:其实SDWebImage之所以能够实现缓存的原理关键就是在哪个key值。
**-** (void)**sd_setImageWithPreviousCachedImageWithURL**:(NSURL *)**url****andPlaceholderImage**:(UIImage *)**placeholder****options**:(SDWebImageOptions)options**progress**:(SDWebImageDownloaderProgressBlock)progressBlock**completed**:(SDWebImageCompletionBlock)completedBlock;
比如使用它的时候,其实就是把url当做了一个图片的key值,然后存储对应的图片,如果下次请求的url和这次请求的url一样,那么就直接根据url(这个key)来取图片,如果url作为key的图片缓存不存在,就去请求远程服务器,然后请求过来之后再次将url和图片对应,然后存储。
2.SDWebImage 概论
1.提供了一个UIImageView的category用来加载网络图片并且对网络图片的缓存进行管理
2.采用异步方式来下载网络图片
3.采用异步方式,使用memory+disk来缓存网络图片,自动管理缓存。
4.支持GIF动画
5.支持WebP格式
6.同一个URL的网络图片不会被重复下载
7.失效的URL不会被无限重试
8.耗时操作都在子线程,确保不会阻塞主线程
9.使用GCD和ARC
注意:SDWebImage 使用NSOperationQueue 线程队列来处理多线程。耗时操作都是在子线程里处理。
_downloadQueue = [NSOperationQueuenew];
_downloadQueue.maxConcurrentOperationCount =6;
最大maxConcurrentOperationCount 最大并发队列为6.
/********************************************************************/
一、****options****所有选项:
|
//失败后重试
SDWebImageRetryFailed = 1 << 0,
//UI交互期间开始下载,导致延迟下载比如UIScrollView减速。
SDWebImageLowPriority = 1 << 1,
//只进行内存缓存
SDWebImageCacheMemoryOnly = 1 << 2,
//这个标志可以渐进式下载,显示的图像是逐步在下载
SDWebImageProgressiveDownload = 1 << 3,
//刷新缓存
SDWebImageRefreshCached = 1 << 4,
//后台下载
SDWebImageContinueInBackground = 1 << 5,
//NSMutableURLRequest.HTTPShouldHandleCookies = YES;
SDWebImageHandleCookies = 1 << 6,
//允许使用无效的SSL证书
//SDWebImageAllowInvalidSSLCertificates = 1 << 7,
//优先下载
SDWebImageHighPriority = 1 << 8,
//延迟占位符
SDWebImageDelayPlaceholder = 1 << 9,
//改变动画形象
SDWebImageTransformAnimatedImage = 1 << 10,
|
/********************************************************************/
UIImageView+WebCache.h
1. UIImageView的category,来添加新的方法。
/* Set the imageView `image` with an `url`,The download is asynchronous and cached.*/
2.- (void)sd_setImageWithURL:(NSURL *)url;
/*@param placeholder The image to be set initially, until the image request finishes.*/
3.- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
/*@param options 主要看SDWebImageOptions的枚举*/
4.- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
/*completedBlock A block called when operation has been completed*/
5.- (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock;
/*同上,只是多了placeholderImage*/
6.- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
/*同上,只是多了SDWebImageOptions枚举*/
7.- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
/*同上,只是多了progress*/
8.- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;
/*PreviousCached*/
9.- (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;
/*以用一组图片生成动画:*/
10.- (void)sd_setAnimationImagesWithURLs:(NSArray *)arrayOfURLs;
11./*Cancel the current download*/
- (void)sd_cancelCurrentImageLoad;
- (void)sd_cancelCurrentAnimationImagesLoad;
/*Show activity UIActivityIndicatorView 菊花显示*/
12.- (void)setShowActivityIndicatorView:(BOOL)show;
/*@param style The style of the UIActivityIndicatorView 菊花样式*/
13.- (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style;
pod 'UIActivityIndicator-for-SDWebImage' 一个帮助使用SDWebImage带有UIActivityIndicator的pod
读.m (使用了objc/runtime.h)
主要有三点:
1\. 先移除已有的operationsd_cancelImageLoadOperationWithKey
2.帮助imageView添加UIActivityIndicatorView操作。
3.使用SDWebImageManager类下载url,并返回相应的block,同时把这个下载operation添加到operationDictionary队列中。
/********************************************************************/
UIButton+WebCache.h
// UIButton加载图片
/*与UIImageView不同的是多了UIControlState*/
1.- (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
/*设置BackgroundImage*/
2.- (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
3.其他的一些方法都是这两个的子集,不在介绍。
读.m 跟UIImageView+WebCache的.m 基本一样。
/********************************************************************/
UIImage+GIF.h 这个类别就是让UIImageView能显示gif 的类别。
/*通过这个方法加载gif*/
1.+ (UIImage *)sd_animatedGIFNamed:(NSString *)name;
主要学习到:加载gif 的原理 实质是一定时间内加载多个image。
1.将gif 文件读取后,转化为data 类型
2.将data 转化为CGImageSourceRef,可以获取组成gif的image的个数。
3.然后重新转化为data-> image
4.利用UIImage的动画属性设置即可:[UIImageanimatedImageWithImages:imagesduration:duration];
/********************************************************************/
UIImage+MultiFormat.h 这个类别就是能加载:多种类型的图片格式png,gif,tiffjpeg.
1.+ (UIImage *)sd_imageWithData:(NSData *)data;
NSData+ImageContentType.h 这个类别是判断图片 data 的类型png,gif,tiffjpeg等。
1.+ (NSString *)sd_contentTypeForImageData:(NSData *)data;
UIView+WebCacheOperation.h这个类别是作为父类的为子类(UIImageView 、UIButton)提供服务的
/*存储operation 到字典、取消operation、移除operation、*/
- (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key;
- (void)sd_cancelImageLoadOperationWithKey:(NSString *)key;
- (void)sd_removeImageLoadOperationWithKey:(NSString *)key;
UIImageView+HighlightedWebCache.h 这个类别是设置UIImageView高亮状态下的image 。
方法和UIImageView+WebCache 一致。
/********************************************************************/
类别看完了,下面是真正SDWebImage 帮我们实现url下载,缓存的类。
核心类
SDWebImageManager.h 是个单例类
/*Returns global SDWebImageManager instance. */
@property (strong,nonatomic,readonly)SDImageCache *imageCache;
@property (strong,nonatomic,readonly)SDWebImageDownloader *imageDownloader;
1.+ (SDWebImageManager *)sharedManager;
/*初始化带有上面两个属性的实例化。*/
2.- (instancetype)initWithCache:(SDImageCache *)cache downloader:(SDWebImageDownloader *)downloader;
/*
SDWebImage 第三方库的核心方法
如果在缓存中不存在,则在给定URL处下载图像,否则返回缓存版本。
@param url The URL to the image
@param options SDWebImageOptions
@param progressBlock SDWebImageDownloaderProgressBlock
@param completedBlock SDWebImageCompletionWithFinishedBlock
*/
3.- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock
completed:(SDWebImageCompletionWithFinishedBlock)completedBlock;
实现过程
1.加锁访问:判断url是否在failedURLs数组中。如果存在则不在持续请求。直接返回失败block。
2.加锁访问:将operation操作对象添加到已存在的runningOperations队列数组。
3. 根据url去缓存中去取key。NSString *key = [self cacheKeyForURL:url];
4.第一步:先去内存(Memory)高速缓存中去取,有则返回image 和CacheType 类型。
UIImage *image = [selfimageFromMemoryCacheForKey:key];
doneBlock(image, SDImageCacheTypeMemory);
第二步:没有继续去磁盘(Disk)高速缓存中去,有则先写入Memory,如空间不足,通过添加通知UIApplicationDidReceiveMemoryWarningNotification得知内存警告,清空缓存。然后返回Disk中的image 和CacheType 类型。
UIImage *diskImage = [selfdiskImageForKey:key];
if (diskImage &&self.shouldCacheImagesInMemory) {
NSUInteger cost =SDCacheCostForImage(diskImage);
[self.memCachesetObject:diskImageforKey:keycost:cost];
}
doneBlock(diskImage, SDImageCacheTypeDisk);
第三步:如果前者仍没有找到,说明所有缓存都不存在该图片,需要下载图片。SDWebImageDownloader类去处理下载使用NSMutableURLRequest使用NSURLSession发起请求。 让SDWebImageDownloaderOperation这个类专门封装NSURLSession请求,并实现NSURLSessionDataDelegate代理,处理接受数据回调。整个url下载完成。
/********************************************************************/
主要类
SDWebImageDownloader.h
发起http请求下载类,NSURLSession发请求,和实现代理。
SDWebImageDownloaderOperation.h
将SDWebImageDownloader数据回调到本类中。
SDImageCache.h
缓存处理对象,存储store,取query,删除remove,清除clear等的操作。
我们可以使用它做本地缓存:
很多时候我们可能拍照得到的一张图片要多个地方使用,那么我们就希望可以把这张图片放到缓存里面,然后每次用这张图片的时候就去通过特定的方式取即可。SDWebImage就有这样的一个类:SDImageCache。该类完美地帮助了我们解决了这个问题。
存图片:
SDImageCache *imageCache = [SDImageCache sharedImageCache];
[imageCache storeImage:imageforKey:@"myphoto"toDisk:YES];
取图片:
SDImageCache *imageCache = [SDImageCache sharedImageCache];
**UIImage** *image = [imageCache imageFromDiskCacheForKey:@"myphoto"];
其他类:
SDWebImageDecoder.h
强制解压缩类 ForceDecode
SDWebImageCompat.h
转换2x,3ximage
SDWebImagePrefetcher.h
预取供将来使用缓存中的某些 Url。在低优先级中下载图像。
// Url 在同一时间预取的最大数目。默认值为 3。
@property (nonatomic, assign) NSUInteger maxConcurrentDownloads
// Prefetcher 的 SDWebImageOptions。默认值为 SDWebImageLowPriority。
@property (nonatomic, assign) SDWebImageOptions options
+ (SDWebImagePrefetcher *)sharedImagePrefetcher
/*删除和取消排队的列表*/
- (void)cancelPrefetching
/*分配让SDWebImagePrefetcher排队预取的 Url 的列表,目前一个图像,一次下载和跳过失败的下载的图像和进行到列表中的下一个图像*/
@parame url 要预取的 Url 的列表
- (void)prefetchURLs:(NSArray *)*urls*
/*分配让SDWebImagePrefetcher排队预取的 Url 的列表,目前一个图像,一次下载和跳过失败的下载的图像和进行到列表中的下一个图像 */
@parame url要预取的 Url 的列表
@parame completionBlock 为预取完毕的回调
- (void)prefetchURLs:(NSArray *)*urls* completed:(void ( ^ ) ( NSUInteger finishedCount , NSUInteger skippedCount ))*completionBlock*
/********************************************************************/
参考:[http://www.cocoachina.com/ios/20141212/10622.html](http://www.cocoachina.com/ios/20141212/10622.html)
[http://www.tuicool.com/articles/rA3IryE](http://www.tuicool.com/articles/rA3IryE)
[http://blog.csdn.net/ios_apple/article/details/24310719](http://blog.csdn.net/ios_apple/article/details/24310719)
https://blog.csdn.net/shifang07/article/details/71511917