美文网首页
SDWebImage源码学习(一) --- SDWebImage

SDWebImage源码学习(一) --- SDWebImage

作者: Maj_sunshine | 来源:发表于2018-03-06 10:06 被阅读46次
第一步还是先学习SDWebImage中还不怎么熟悉的知识点

知识点1 --- #error

用来做显示编译出错内容。


知识点2 --- FOUNDATION_EXPORT

我们经常用#define 都可以用来定义常量,其实还可以使用FOUNDATION_EXPORT定义常量。

  • FOUNDATION_EXPORT源码中的使用
// .h文件中
FOUNDATION_EXPORT NSString *const SDWebImageErrorDomain

// .m文件中
NSString *const SDWebImageErrorDomain = @"SDWebImageErrorDomain";

  • define关键字使用
#define kMyConstantString @"Hello"

第二种是最简单的宏的写法,但是第一种方法在检测字符串的值是否相等的时候更快。对于第一种可以直接使用(stringInstance == MyFirstConstant)来比较,而define则使用的是这种.([stringInstance isEqualToString:MyFirstConstant])。第一种直接比较的是指针地址,而第二个则是一一比较字符串的每一个字符是否相等,第一种效率高.


知识点3 --- dispatch_queue_async_safe

源码

#ifndef dispatch_queue_async_safe
#define dispatch_queue_async_safe(queue, block)\
    if (strcmp(dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL), dispatch_queue_get_label(queue)) == 0) {\
        block();\
    } else {\
        dispatch_async(queue, block);\
    }
#endif

#ifndef dispatch_main_async_safe
#define dispatch_main_async_safe(block) dispatch_queue_async_safe(dispatch_get_main_queue(), block)
#endif
  • 这个宏的定义其实一个#define里面有多行代码 ,我们在写这种宏的时候可以用换行符来分割。我们自己的项目中非常多的地方需要用到登陆的判断,如果用户没有登录就前去登录。代码也可以写成宏。
// 前往登录
#define SWCheckLogin \
UIViewController *loginMainVC = [[HHRouter shared] matchController:SW_Login_LoginMain];\
loginMainVC.view.backgroundColor = kGetColor(255, 255, 255, 1.0); \
SWNavigationController *loginNav = [[SWNavigationController alloc] initWithRootViewController:loginMainVC]; \
[self presentViewController:loginNav animated:YES completion:nil]; \

这样在登录的时候,只需SWCheckLogin即可。

  • strcmp关键字
    都要忘了这个C关键字,
    用来比较两个字符串是否相等。
    若str1==str2,则返回零;
    若str1<str2,则返回负数;
    若str1>str2,则返回正数。

  • dispatch_queue_get_label
    用来获取当前队列的名称

  • dispatch_queue_async_safe(<#queue#>, <#block#>)
    在这里主要为了做安全判断

总结起来这代码意思就是获取的线程名称如果和主线程名称相同,则当前线程是主线程,直接调用block,如果不是,调用dispatch_async(dispatch_get_main_queue(), block)。


知识点4 --- NS_OPTIONS和NS_ENUM
  • NS_OPTIONS和NS_ENUM都是都C语言中enum的封装,区别NS_OPTIONS用于位移类型的enum,NS_ENUM用于普通enum。
    举个例子
  • NS_OPTIONS
typedef NS_OPTIONS(NSUInteger, UIControlEvents) {
    UIControlEventTouchDown                                         = 1 <<  0,      // on all touch downs
    UIControlEventTouchDownRepeat                                   = 1 <<  1,      // on multiple touchdowns (tap count > 1)
    UIControlEventTouchDragInside                                   = 1 <<  2,
    UIControlEventTouchDragOutside                                  = 1 <<  3,
    UIControlEventTouchDragEnter                                    = 1 <<  4,
    UIControlEventTouchDragExit                                     = 1 <<  5,
    UIControlEventTouchUpInside                                     = 1 <<  6,
    UIControlEventTouchUpOutside                                    = 1 <<  7,
    UIControlEventTouchCancel                                       = 1 <<  8,
}

事件的类型就是个NS_OPTIONS。
从上到下的值分别是二级制的
0000 0001 , // 1 * 2^0 = 1
0000 0010, // 1 * 2^1 = 2
0000 0100, // 1 * 2^2 = 4
0000 1000, // 1 * 2^3 = 8
0001 0000, // 1 * 2^4 = 16
0010 0000, // 1 * 2^5 = 32
0100 0000, // 1 * 2^6 = 64
1000 0000, // 1 * 2^7 = 128
比如要去这个枚举的下面三个枚举值

UIControlEventTouchUpInside| UIControlEventTouchUpOutside| UIControlEventTouchDown

这样我们就可以获取到这个枚举的确定唯一的枚举值0110 0001,值为128 + 64 + 1 = 193;位运算保证了这个数字的唯一性。以次来获取枚举组合。

  • 普通枚举NS_ENUM
    再拿来一个系统枚举
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
   UIViewAnimationCurveEaseInOut,         // slow at beginning and end
   UIViewAnimationCurveEaseIn,            // slow at beginning
   UIViewAnimationCurveEaseOut,           // slow at end
   UIViewAnimationCurveLinear,
};
从上到下依次为 0 1 2 3 ,普通枚举做不到两张值都获取, 因为组合枚举值做不到唯一性 。


知识点5- -- inline
  • 作用

1 解决函数调用效率问题。inline函数避免了普通函数的,在汇编时必须调用call的缺点:取消了函数的参数压栈,减少了调用的开销,提高效率.

2 用于替代宏,跟宏一样使用时进行了代码替换,这里是使用函数体替换了函数名,相比于宏,内联函数调用的时候会检查参数的类型,确保调用正确,而且内联函数也是函数,去除了预编译的过程。

  • 注意 内联函数的函数体内代码尽量不要过长或出现循环体,否则函数的执行编译器可能会放弃内联。

知识点6 --- #if !__has_feature(objc_arc)

源码

#if !__has_feature(objc_arc)
#error SDWebImage is ARC only. Either turn on ARC for the project or use -fobjc-arc flag
#endif

意为如果当前环境不是ARC则编译报上述错,SDWebImage仅支持ARC环境。


知识点7 --- animatedImageWithImages:duration:

源码

 UIImage *animatedImage = [UIImage animatedImageWithImages:scaledImages duration:image.duration];

我们提供一个图片数组,方法执行播放起来就像是一个个图片的帧动画,duration为方法的执行时间
动画的重复次数是由animationRepeatCount控制,0为一直重复。动画停止stopAnimating方法。


知识点8 --- NSMutableArray<UIImage *>

作用 : 用来标记数据中每个对象的类型,不标记时取出数组的数不初始化时都为id类型,标记后为UIImage 类型,可以使用这个类型的方法列表中的方法。

例: 项目中我们经常使用数组作容器放model,我们可以这样

@property (nonatomic, strong) NSMutableArray<SWMyFansOrLikesModel *> *dataArray

这样我们要调用这个数组的数据就不用

SWMyFansOrLikesModel *model = self.viewModel.dataArray[indexPath.row];
UIViewController *infoDeatil = [[HHRouter shared] matchController:[NSString stringWithFormat:@"%@?userId=%@",SW_UserInfo,model.userID]];

可以直接调用

UIViewController *infoDeatil = [[HHRouter shared] matchController:[NSString stringWithFormat:@"%@?userId=%@",SW_UserInfo,self.viewModel.dataArray[indexPath.row].userID]];

在tableView的didSelectRowAtIndexPath方法中去除model初始化的操作,这样子控制器就不必要导入model的头文件。


知识点8 --- 返回对应分辨率下面的图片

来看看源码中的实现

if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
            CGFloat scale = 1;
            if (key.length >= 8) {
                NSRange range = [key rangeOfString:@"@2x."];
                    // “@2x.png”的长度为7
                if (range.location != NSNotFound) {
                    scale = 2.0;
                }
                
                range = [key rangeOfString:@"@3x."];
                if (range.location != NSNotFound) {
                    scale = 3.0;
                }
            }

            UIImage *scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
            image = scaledImage;
        }

我们同在在调用图片的时候使用[UIImage imageNamed:@"xxx"],xcode会自动帮我们根据屏幕分辨率添加@2x @3x操作,进而查找图片。如果我们在你调用图片时候调用[UIImage imageNamed:@"xxx@2x"],xcode的会把xxx@2x 当名称 再根据分辨率添加@2x @3x操作 后,变成[UIImage imageNamed:@"xxx@2x@2x"]查找,找不到xcode会把图片当一倍图,导致了图片的拉伸。但是源码中的这个方法,[UIImage imageNamed:@"xxx@2x@2x"] ,SDWebImage会处理成 scale = 2.0;从而加载正确图片。

总结

SDWebImageCompat这个文件可以看成一个配置文件,写的是各平台兼容的宏,.m文件各个方法其实可以看成宏的替换内容。

相关文章

网友评论

      本文标题:SDWebImage源码学习(一) --- SDWebImage

      本文链接:https://www.haomeiwen.com/subject/afdexftx.html