SDWebImage中的- (void)sd_setImageWithURL:(NSURL *)url方法分析

来源:互联网 发布:海洋最深处 知乎 编辑:程序博客网 时间:2024/05/22 12:37

经常有面试官问到SDWebImage的请求过程。感觉有必要写下来。

查看UIImageView+WebCache.m文件:

- (void)sd_setImageWithURL:(NSURL *)url

这个方法有指定的初始化函数,所谓的指定的初始化函数,就是函数最多。下面这个方法就就是了:

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock

首先第一句是:

[self sd_cancelCurrentImageLoad];

查看UIView+WebCacheOperation.m文件:
这个是一个处理线程的文件。里面包含,线程字典初始化,线程字典设置,线程字典取消,线程字典删除。
然后是这句:

objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

将url保存在imageURLKey这个key中。


然后是这句:

if (!(options & SDWebImageDelayPlaceholder)) {        dispatch_main_async_safe(^{            self.image = placeholder;        });    }

首先这句:
options & SDWebImageDelayPlaceholder,这个是一个位运算的与操作。翻译就是,如果options参数不是SDWebImageDelayPlaceholder,就执行以下操作。
那么,SDWebImageDelayPlaceholder是什么?看定义,默认情况下,在请求的图片正在加载的时候,占位图已加载完毕。这个标记将会延迟占位图,直到请求的图片加载完成。
看下一句:

dispatch_main_async_safe

这个是作者自己定义的。定义如下:

#define dispatch_main_async_safe(block)\    if ([NSThread isMainThread]) {\        block();\    } else {\        dispatch_async(dispatch_get_main_queue(), block);\    }

这表示,在主线程上面去执行这段函数,加载占位图。


接下来判断url是否存在,不存在发出错误信号。正确的话,执行:

if ([self showActivityIndicatorView]) {            [self addActivityIndicator];        }

这句话添加加载视图。
然后是这句:

__weak __typeof(self)wself = self;

这个是避免循环引用而使用的,传递self。


看下一句,调用以下的方法:

- (id <SDWebImageOperation>)downloadImageWithURL:options:progress:completed:

看方法实现转到文件SDWebImageManager.m中:
首先是这两句:

if ([url isKindOfClass:NSString.class]) {        url = [NSURL URLWithString:(NSString *)url];    }if (![url isKindOfClass:NSURL.class]) {        url = nil;    }

这是判断url的。
然后是这句:

__block SDWebImageCombinedOperation *operation = [SDWebImageCombinedOperation new];    __weak SDWebImageCombinedOperation *weakOperation = operation;

先看一下SDWebImageCombinedOperation,这个类是实现SDWebImageOperation接口的,主要是用来发起线程和取消线程。
接下来看一下:

BOOL isFailedUrl = NO;    @synchronized (self.failedURLs) {        isFailedUrl = [self.failedURLs containsObject:url];    }

@synchronized这是一个互斥锁,保证此时没有其它线程对self对象进行修改。这段代码的作用是判断当前的url是否在失败url的set集合当中。
接下来这句:

if (url.absoluteString.length == 0 || (!(options & SDWebImageRetryFailed) && isFailedUrl)) {

这句操作表示如果urlstring长度为0,或者请求失败的set集合中包含这个url,且请求的选项不是失败后重试的话,那么就返回错误代码。
然后是这句:

@synchronized (self.runningOperations) {        [self.runningOperations addObject:operation];    }

将当前线程加入正在运行的队列数组中。
然后这句:

NSString *key = [self cacheKeyForURL:url];

将url转成字符串,作为Key。


接下来是这句:

operation.cacheOperation = [self.imageCache queryDiskCacheForKey:key done:^(UIImage *image, SDImageCacheType cacheType) {

根据key到缓存中查询该图片。然后跳到SDImageCache.m该文件。


篇幅问题,直接贴图了:
SDWebImage的执行流程

0 0
原创粉丝点击