转载

[SourceRead]-SDWebImage-2

[1]宏定义

dispatch_main_sync_safedispatch_main_async_safe 是SDWebImage定义的两个宏。若当前是主线程,则执行block;若不是主线程,则在主线程中同步/异步之行block。

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

每行后面的反斜杠 / 表示在不影响含义的条件下换行,需注意要在回车之前加反斜杠 /

再看一个常见的宏定义。

#define DLog(fmt, ...)    NSLog( @"<%@:(%d)> %s /n ----- %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, __func__, [NSString stringWithFormat:(fmt), ##__VA_ARGS__] ) 

这个用于Log的宏定义中,有这样几点需要解释的:

  • DLog(fmt, ...) 的第二个参数 ... 。在宏定义的时候,写为…的参数被叫做可变参数(variadic),其个数是不限定的。在这里,第一个参数fmt将被单独处理,后面的参数将被作为整体看待。
  • 通常前后被 __ 包围的都是预定义宏。如这里的 __FILE__ (当前文件的绝对路径), __LINE__ (在文件中的行数), __func__ (该宏所在的行所属的函数名)。
  • ##__VA_ARGS__ 表示的是宏定义中的…中的所有剩余参数。打头的 ## 表示将两个参数连接起来这种运算。

[2] SDWebImageOptions 中几个有趣的枚举值

typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {     ...     /**      * 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.      */     SDWebImageDelayPlaceholder = 1 << 9,     ...         /**      * By default, image is added to the imageView after download. But in some cases, we want to      * have the hand before setting the image (apply a filter or add it with cross-fade animation for instance)      * Use this flag if you want to manually set the image in the completion when success      */     SDWebImageAvoidAutoSetImage = 1 << 11 

在上一篇中提到的 核心方法 中,有这样几个 SDWebImageOptions 引起了我的注意。

一个是 SDWebImageDelayPlaceholder 。说是默认情况下,placeholder的图片会在网络图片加载的过程中就被加载完毕,这个flag会将placeholder图片等加载延迟到网络图片完成加载之后。所以这里

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

是说如果使用者传入的 options 不是 SDWebImageDelayPlaceholder ,就正常地把placeholder图片赋给当前的 imageView 。之前第一遍看时没有看懂,原来就是“负负得正”的意思。

另一个是 SDWebImageAvoidAutoSetImage 。默认情况下,图片会在下载完毕后 自动 添加给 imageView 。但有些时候,比如说我们想在设置图片之前加一些图片处理(加个滤镜或者渐变动画之类的),就需要在下载成功时 手动 使用这个flag来设置图片了。 以后想实现类似效果就知道该在哪里设置什么参数了。

if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock) {         completedBlock(image, error, cacheType, url);         return; } 

所以这里判断,如果image不为空,而 options 表明需要增加图片处理,且加载完成的 completeBlock 不为空,那么就代入参数,执行 completeBlock

[3] setNeedsLayoutlayoutIfNeeded

接着上面的if判断:

else if (image)  {          wself.image = image;          [wself setNeedsLayout]; }  else {           if ((options & SDWebImageDelayPlaceholder)) {                   wself.image = placeholder;                   [wself setNeedsLayout];           }  } 

如果后两个条件中至少有一个不满足,那么就直接将image赋给当前的 imageView ,并调用 setNeedsLayout 将其标记为需要重新布局;如果image为空,而 options 表明需要延迟加载placeholder图片,那么就将placeholder图片赋给当前 imageView ,并将其标记为需要重新布局。

setNeedsLayout 紧密相关的 layoutIfNeeded 用于实现布局。比如使用了AutoLayout的 UITableViewCell 中经常会这样二者连着写:

- (void)layoutSubviews {     [super layoutSubviews];      [self.contentView setNeedsLayout];     [self.contentView layoutIfNeeded]; } 

具体iOS绘制UI的原理及步骤,这里算是给自己挖了个坑吧,以后看懂了、研究明白了再慢慢填上。

Ref:

  • 喵神讲解宏定义黑魔法的一篇: http://onevcat.com/2014/01/black-magic-in-macro/
原文  http://www.calios.gq/2016/01/31/[SourceRead]-SDWebImage-2/
正文到此结束
Loading...