设为首页 加入收藏

TOP

【原】SDWebImage源码阅读(一)(二)
2017-10-12 12:06:51 】 浏览:10429
Tags:SDWebImage 源码 阅读
17 } 18 } 19 20 @end

ViewController调用代码:

 1 #import "ViewController.h"
 2 #import "UIImageView+Extension.h"
 3 
 4 @interface ViewController ()
 5 
 6 @property (weak, nonatomic) IBOutlet UIImageView *imageView;
 7 
 8 @end
 9 
10 @implementation ViewController
11 
12 #pragma mark - life cycle
13 - (void)viewDidLoad {
14     [super viewDidLoad];
15     
16     NSString *baiduLogoString = @"https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png";
17     
18     [self.imageView pjx_setImageWithURL:[NSURL URLWithString:baiduLogoString] placeholderImage:[UIImage imageNamed:@"placeholderImage"]];
19 }
20 
21 @end

效果如下:

没有网络(左)有网络(右)情况下的对比图

 

然后我喜滋滋地去看SDWebImage的sd_setImageWithURL:placeholderImage:实现,结果~~他居然调用的是另外一个巨多参数的函数:

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

大概猜下,除了url和placeholder两个参数懂是什么意思,options不明白,progress肯定表示的是下载的进度,也就是正在下载时候所要处理的事情(block),那么completed应该表示的是下载完成后所要做的事(block)

于是我定位到了该函数,发现自己完全不是一个级别上的,看不懂。不过我还不死心,于是我全局搜索dataWithContentsOfURL,嗯,SDWebImage居然没有用!好吧,先不管了,不用就不用,那你总得给UIImageView的image赋值吧,而且肯定要赋值一次placeholderImage和网络请求得到的image吧。果然找到了,就在上面那个巨多参数的函数中。我只截取了部分代码

 1 ......
 2 if (!(options & SDWebImageDelayPlaceholder)) {
 3     dispatch_main_async_safe(^{
 4         self.image = placeholder;
 5     });
 6 }
 7 .....
 8 else if (image) {
 9     wself.image = image;
10     [wself setNeedsLayout];
11 } else {
12     if ((options & SDWebImageDelayPlaceholder)) {
13         wself.image = placeholder;
14         [wself setNeedsLayout];
15     }
16 }
17 ...

可以看到这里实现了三处image的赋值。并且后面两处赋值后立即使用setNeedsLayout来进行刷新(我注释了刷新代码,好像没有发生什么问题,不过这里还是注意一下,肯定是某个情形下会发生无法自动刷新图片的情况,才要手动刷新)。好的,这里我们可以停一下,看看这些image赋值都是发生在什么情况下的。

这几处赋值都出现了SDWebImageDelayPlaceholder。看下它的注释,首先,它是一个SDWebImageOptions枚举值,而参数options也是一个枚举类型的变量,注定两者是好基友了。话说回来,SDWebImageDelayPlaceholder表示的是什么呢?看注释:

    /**
     * By default, placeholder images are loaded while the image is loading. This flag will delay the loading
     * of the placeholder image until after the image has finished loading.
     */

翻译过来就是,默认情况下,当正在加载网络端的image 时,placeholder已经加载到了UIImageView,这个枚举项就是为了避免这种默认情况,他将延迟placeholder的加载直到网络端的image加载完成。可能有些抽象,看代码就行了。

在还没发送请求获取网络端图片之前(即网络端的image还没加载),如果options中有SDWebImageDelayPlaceholder这一选项,就不给image赋值,如果没有这一项,那么就给image赋值placeholder。说白了就是下面这段代码:

1 if (!(options & SDWebImageDelayPlaceholder)) {
2     dispatch_main_async_safe(^{
3         self.image = placeholder;
4     });
5 }

其中dispatch_main_async_safe就是SDWebImage定义的一个宏,很好理解:如果当前是主进程,就直接执行block,否则把block放到主进程运行。为什么要判断是否是主进程?因为iOS上任何UI的操作都在主线程上执行,所以主进程还有一个名字,叫做“UI进程”。

1 #define dispatch_main_async_safe(block)\
2     if ([NSThread isMainThread]) {\
3         block();\
4     } else {\
5         dispatch_async(dispatch_get_main_queue(), block);\
6     }

后面我们看到有一处代码,表示即使options中有SDWebImageDelayPlaceholder这一选项,也给image赋值placeholder,为啥了?因为此时image已经从网络端加载过了,但是网络端获取image没成功,此时才会用placeholder来替代,赤裸裸的备胎,有代码为证。

else { // image已经尝试获取过了,但是没有从网络端获取到
    if ((options & SDWebImageDelayPlaceholder)) {
        wself.image = plac
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇UINavigationController 导航控制.. 下一篇一个裁剪图片的小工具类,通过一句..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目