前言:
因为SDWebImage这个框架真的太常用了,所以具体的使用方法就不在这里做细说,下文也只会提到简单的方法用, SDWebImage的github文档中有说明使用SDWebImage的github传送门;
官方结构图
1.SDWebImage的一些类
1.1 UIView(WebCache)
我们可以看到源码中提供了如下类别:
UIImageView(WebCache)
/SDAnimatedImageView(WebCache)
/UIButton(WebCache)
这些类别声明了可直接调用的加载图片的方法,而最后这些暴露的方法最后会统一调用UIView(WebCache)
里面的方法:sd_internalSetImageWithURL:...
案例代码:
/**加载gif图片*/
-(void)method2{
NSURL *gifURL = [NSURL URLWithString:url2];
/**
加载图片的方法
@param URL 图片链接
@param placeholderImage 展位图
@param options 加载策略,是一个枚举
@param progress 加载进度回调
@param completed 加载完成回调
*/
/*
options:
SDWebImageRetryFailed -> 下载失败后,会重新下载
SDWebImageLowPriority -> 低优先级,当有视图滚动的时候先暂停加载
SDWebImageProgressiveLoad -> 显示进度,图片一点一点显示;
SDWebImageRefreshCached -> 每一次都会重新加载图片,
SDWebImageContinueInBackground->应用在后台的时候还可以加载图片
SDWebImageHandleCookies->是否处理cookies
SDWebImageHighPriority->高优先级
SDWebImageDelayPlaceholder->imageholder在加载完图片的时候才出现,没什么意义这个设置
这个枚举还有很多别的值情况,详细请到源码中查询
*/
[self.sdImageView sd_setImageWithURL:gifURL placeholderImage:nil options:SDWebImageRefreshCached progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL *targetURL) {
//获得下载进度
//receivedSize 收到的数据大小
//expectedSize 期待收到的数据大小->下载目标的大小
//targetURL 下载的url
NSLog(@"url:%@",targetURL);
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
//加载结束回调
//image 图片本身
//error 如果发生错误则返回error,否则error=nil
//cacheType 加载图片的模式
/*
SDImageCacheTypeNone, 0 表示图像不再内存中,是从网络获取的
SDImageCacheTypeDisk, 1 图片在沙盒中获取
SDImageCacheTypeMemory, 2 图片是从运行的内存从中获取的
SDImageCacheTypeAll, 所有的情况 (在删除SD缓存的时候也用到这个枚举)
*/
NSLog(@"image.size:%@",NSStringFromCGSize(image.size));
}];
}
1.2 SDImageCache
在SDWebImage
这个框架中,提供了一个SDImageCache
协议,和一个SDImageCache
类
SDImageCache
协议-> 提供了关于图片的缓存处理方法:
SDImageCache
类-> 在其初始化的时候,添加了三个监听:
#if SD_UIKIT
// Subscribe to app events
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate:)
name:UIApplicationWillTerminateNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
#endif
#if SD_MAC
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillTerminate:)
name:NSApplicationWillTerminateNotification
object:nil];
#endif
1.3 SDWebImageManager
SDWebImageManager
->框架的管理者,继承于NSObject
,它是一个单例,在其初始化方法的内部直接为其属性初始化:
+ (nonnull instancetype)sharedManager {
static dispatch_once_t once;
static id instance;
dispatch_once(&once, ^{
instance = [self new];
});
return instance;
}
- (nonnull instancetype)init {
id<SDImageCache> cache = [[self class] defaultImageCache];
if (!cache) {
cache = [SDImageCache sharedImageCache];
}
id<SDImageLoader> loader = [[self class] defaultImageLoader];
if (!loader) {
loader = [SDWebImageDownloader sharedDownloader];
}
return [self initWithCache:cache loader:loader];
}
- (nonnull instancetype)initWithCache:(nonnull id<SDImageCache>)cache loader:(nonnull id<SDImageLoader>)loader {
if ((self = [super init])) {
_imageCache = cache;
_imageLoader = loader;
_failedURLs = [NSMutableSet new];
_failedURLsLock = dispatch_semaphore_create(1);
_runningOperations = [NSMutableSet new];
_runningOperationsLock = dispatch_semaphore_create(1);
}
return self;
}
-
SDWebImageDownloader
下载管理类类,但是其最终任务不是用这个类来执行,而是派发到 :SDWebImageDownloaderOperation
这个类来执行的.它继承于NSOperation;
SDWebImageDownloader
的实例对象可以通过其属性defaultDownloaderConfig
进行配置设置,因为defaultDownloaderConfig
是一个只读属性,所以只能通过调用以下方法进行设置:
- (nonnull instancetype)initWithConfig:(nullable SDWebImageDownloaderConfig *)config;
//defaultDownloaderConfig 提供的属性有:
//maxConcurrentDownloads //最大下载数 默认6
//downloadTimeout //下载超时 默认15秒
//minimumProgressInterval //进度回调的精度 0.0-1.0 越小越精确
//还有别的属性,不会常用到,不一一罗列
2.使用什么下载方式?
在SDWebImageDownloaderOperation.m
文件中使用了NSURLSession
的下载方式进行图片下载,2016年的时候是用的NSURLConnection
的方式来进行下载的,后来改版了
3.加载完成后的处理
3.1存放路径
Library/Caches/com.hackemist.SDImageCache/default
3.2命名规则
下载链接进行MD5加密后拼接上文件后缀就是加载的文件命名
3.3如何判断下载的图片类型 JPG?/PNG?/GIF?
NSData+ImageContentType
这个类提供了一个判断类型的方法,改方法根据二进制文件的第一个字节判断二进制文件的类型;
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
/*SDImageFormat是一个枚举类型:
typedef NSInteger SDImageFormat NS_TYPED_EXTENSIBLE_ENUM;
static const SDImageFormat SDImageFormatUndefined = -1;
static const SDImageFormat SDImageFormatJPEG = 0;
static const SDImageFormat SDImageFormatPNG = 1;
static const SDImageFormat SDImageFormatGIF = 2;
static const SDImageFormat SDImageFormatTIFF = 3;
static const SDImageFormat SDImageFormatWebP = 4;
static const SDImageFormat SDImageFormatHEIC = 5;
static const SDImageFormat SDImageFormatHEIF = 6;
*/
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data {
if (!data) {
return SDImageFormatUndefined;
}
// File signatures table: http://www.garykessler.net/library/file_sigs.html
uint8_t c;
[data getBytes:&c length:1];
switch (c) {
case 0xFF:
return SDImageFormatJPEG;
case 0x89:
return SDImageFormatPNG;
case 0x47:
return SDImageFormatGIF;
case 0x49:
case 0x4D:
return SDImageFormatTIFF;
case 0x52: {
if (data.length >= 12) {
//RIFF....WEBP
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
return SDImageFormatWebP;
}
}
break;
}
case 0x00: {
if (data.length >= 12) {
//....ftypheic ....ftypheix ....ftyphevc ....ftyphevx
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(4, 8)] encoding:NSASCIIStringEncoding];
if ([testString isEqualToString:@"ftypheic"]
|| [testString isEqualToString:@"ftypheix"]
|| [testString isEqualToString:@"ftyphevc"]
|| [testString isEqualToString:@"ftyphevx"]) {
return SDImageFormatHEIC;
}
//....ftypmif1 ....ftypmsf1
if ([testString isEqualToString:@"ftypmif1"] || [testString isEqualToString:@"ftypmsf1"]) {
return SDImageFormatHEIF;
}
}
break;
}
}
return SDImageFormatUndefined;
}