【iOS】SDWebImage

article/2025/10/8 2:16:46

文章目录

  • SDWebImage
    • 日常使用
    • 一些主要功能
      • 获取图片缓存
    • 缓存机制
      • 独立的异步图像下载
      • 独立的异步图像缓存
    • 图片加载全过程
  • 源码分析
    • 架构图
    • 结构
      • SDWebImageManager
        • 1. SDWebImageOptions
        • 2. SDWebImageManagerDelegate
      • SDWebImageCompat
        • SDWebImageCompat.h
        • SDWebImageCompat.m
      • sd_imageIndicator
      • UIImageView+WebCache层

SDWebImage

SDWebImage具有缓存支持的异步映像下载程序。并添加了像UI元素分类类UIImageView、UIButton、MKAnnotationView,可以直接为这些UI元素添加图片。

日常使用

在日常的使用中,通常是加载网络图片到UIImageView上展示,所以一般在需要使用SDWebImage的文件中只引用#import "UIImageView+WebCache.h"头文件。

最简单的加载方式是只加载图片地址:

UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:imageView];[imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]];

当然,SDWebImage也提供了其他的加载方法,不过点击方法进入查看后,发现最终都是调用其全能方法:

- (void)sd_setImageWithURL:(nullable NSURL *)url {[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil];
}

全能方法除了必需的的图片地址,还提供了占位图、可选项、加载进度和完成回调。

- (void)sd_setImageWithURL:(nullable NSURL *)urlplaceholderImage:(nullable UIImage *)placeholderoptions:(SDWebImageOptions)optionsprogress:(nullable SDWebImageDownloaderProgressBlock)progressBlockcompleted:(nullable SDExternalCompletionBlock)completedBlock;

紧接着我们点击进入全能方法中:

- (void)sd_setImageWithURL:(nullable NSURL *)urlplaceholderImage:(nullable UIImage *)placeholderoptions:(SDWebImageOptions)optionsprogress:(nullable SDWebImageDownloaderProgressBlock)progressBlockcompleted:(nullable SDExternalCompletionBlock)completedBlock {[self sd_internalSetImageWithURL:urlplaceholderImage:placeholderoptions:optionsoperationKey:nilsetImageBlock:nilprogress:progressBlockcompleted:completedBlock];
}

可以发现,全能方法并没有什么实际的实现,只是对另一个方法的封装。

一些主要功能

  1. UIImageViewUIButtonMKAnnotationView添加Web图像和告诉缓存管理
  2. 异步图像下载器
  3. 具有自动缓存到期处理的异步内存+磁盘映像缓存
  4. 背景图像解压缩
  5. 对动画图像的支持
  6. 可以自定义和组合的转换,可在下载后立即应用于图像
  7. 可以自定义加载器(如照片库)来扩展图像加载功能
  8. 加载中的indicator显示
  9. 保证不会下载相同的URL
  10. 下载过程或者资源保存过程用到了GCDARC
  11. 提前将获取到的图片放到主线程,保证不会阻塞主线程

获取图片缓存

在图片加载的方法实现中,可以看到有比较重要的两个方法,一个是获取图片缓存,另一个是从网络下载图片。在这一节,我们先看获取图片缓存:

- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options done:(nullable SDCacheQueryCompletedBlock)doneBlock;

点击方法进入查看其实现:

- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options done:(nullable SDCacheQueryCompletedBlock)doneBlock {// 如果没传参数key就直接回调并返回,就不继续向下执行了if (!key) {if (doneBlock) {doneBlock(nil, nil, SDImageCacheTypeNone);}return nil;}// 先根据key查找内存中是否有缓存UIImage *image = [self imageFromMemoryCacheForKey:key];// 如果有缓存图片,并且没设置强制从硬盘中查找缓存,就直接回调并返回了BOOL shouldQueryMemoryOnly = (image && !(options & SDImageCacheQueryDataWhenInMemory));if (shouldQueryMemoryOnly) {if (doneBlock) {doneBlock(image, nil, SDImageCacheTypeMemory);}return nil;}// 生成一个操作对象NSOperation *operation = [NSOperation new];// 生成一个查询硬盘缓存的代码块void(^queryDiskBlock)(void) =  ^{// 如果操作取消就直接返回,不执行回调if (operation.isCancelled) {// do not call the completion if cancelledreturn;}// 生成一个自动释放池@autoreleasepool {// 根据key查找硬盘中是否有缓存NSData *diskData = [self diskImageDataBySearchingAllPathsForKey:key];UIImage *diskImage;SDImageCacheType cacheType = SDImageCacheTypeDisk;if (image) {// 如果内存中有缓存diskImage = image;cacheType = SDImageCacheTypeMemory;} else if (diskData) {// 如果内存中没有缓存但是硬盘中有缓存diskImage = [self diskImageForKey:key data:diskData];if (diskImage && self.config.shouldCacheImagesInMemory) {NSUInteger cost = SDCacheCostForImage(diskImage);[self.memCache setObject:diskImage forKey:key cost:cost];}}// 如果设置了同步查询硬盘缓存的选项就直接调用,否则就主队列异步回调if (doneBlock) {if (options & SDImageCacheQueryDiskSync) {doneBlock(diskImage, diskData, cacheType);} else {dispatch_async(dispatch_get_main_queue(), ^{doneBlock(diskImage, diskData, cacheType);});}}}};// 如果设置了同步查询硬盘缓存的选项就直接调用,否则就自定义·串行队列异步回调if (options & SDImageCacheQueryDiskSync) {queryDiskBlock();} else {dispatch_async(self.ioQueue, queryDiskBlock);}return operation;
}

获取图片缓存的逻辑还是很清晰的:

  • 首先查找在内存中的缓存,再根据设置的选项决定要不要继续查找。
  • 然后根据设置的选项决定是同步还是异步查找硬盘中的缓存。
  • 接着根据设置的选项决定要不要把硬盘中的缓存图片缓存到内存中。
  • 最后进行回调数据

缓存机制

独立的异步图像下载

可能会用到单独的异步图片下载,则一定要用 - (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionWithFinishedBlock)completedBlock; 来建立一个SDWebImageDownLoader 的实例。这样就可以有下载进度的回调和下载完成的回调,可以在回调完成进度条相关的操作和显示图片相关的操作。

独立的异步图像缓存

SDImageCache类提供一个管理缓存的单例类。

SDImageCache *imageCache = [SDImageCache sharedImageCache];

查找和缓存图片时以URL作为key。(先查找内存,如果内存不存在该图片,再查找硬盘;查找硬盘时,以URLMD5值作为key).

图片加载全过程

在这里插入图片描述

  1. 我们在使用SDWebImage时调用了[imageView sd_setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]];这个简单的分类方法,然后就静静的等着图片被设置到UIImageView类对象上。
  2. 经过一系列调用,我们首先来到UIView+WebCache分类中,在这个分类中,首先保障了图片加载的唯一性,然后就开始了核心的加载操作。
  3. 接着就进入了SDWebImageManager类中,在这个类中,首先去查找是否有缓存,没有缓存的话才去服务器下载。
  4. 想要查找缓存我们要进入SDImageCache这个类中,在这个类中,首先去内存中查看是否有对应的缓存,如果没有再去硬盘中查找是否有对应的缓存,但是从硬盘中获取的是图片的数据,要想获得图片还要经历解码、缩放和解压。当然如果都没有缓存的话就去下载。
  5. 负责下载的是SDWebImageDownloader这个类,在这个类中,将图片的下载操作封装成了自定义的一个类SDWebImageDownloaderOperation,然后添加到了操作队列中。
  6. 当操作队列调用这个操作时,会调用操作对象的- (void)start方法,在重写的这个方法中,生成了任务对象dataTask,并调用resume开始执行任务。
  7. 因为SDWebImageDownloaderOperation类遵守了dataTask对象的协议,所以dataTask执行的结果会通过代理方法进行回调。在代理方法中,获取并保存了服务器返回的数据,并在任务执行结束后,对数据进行解码、缩放和解压。处理完成后就进行回调。
  8. 通过重重回调,要回调的数据沿着SDWebImageDownloaderOperation->SDWebImageDownloader->SDWebImageManager->UIView+WebCache一路流动,其中流动到SDWebImageManager中时对图片进行了缓存,最后在UIView+WebCache中为UIImageView设置了处理好的图片。

源码分析

架构图

在这里插入图片描述
从SDWebImage中提供的架构图中我们可以大概的看出,整个库分为两层,Top Level、Base Module。

  • Top Level:当UIImageView调用加载image方法,会进入SDWebImage中的UIImageView分类,在分类中调用负责加载UIImage的核心代码块ImageManager,其主要负责调度Image Cache/Image Loader,这两者分别从缓存或者网络端加载图片,并且又进行了细分。Cache中获取图片业务,拆分到了memory/disk两个分类中;Image Loader中又分为从网络端获取或者从系统的Photos中获取。
  • Base Module:获取到图片的二进制数据处理,二进制解压缩,二进制中格式字节判断出具体的图片类型。

结构

(设计思路借鉴:提供多种接口,到底层调用到同一个方法,减少调用方对可选参数的传递)

  • UIImageView+WebCacheUIButton+WebCache直接为表层的 UIKit框架提供接口,
  • SDWebImageMangerSDWebImageManagerSDWebImage的核心类,也是我们经常接触到的类)负责处理和协调SDWebImageDownloaderSDWebImageCache, 并与UIKit层进行交互。SDWebImageDownloaderOperation真正执行下载请求;
  • SDWebImageCompat 是最基础的配置文件,为了兼容苹果各个平台
  • SDWebImageDecoder sd解码图片这个类其实是UIImage的一个分类UIImage+ForceDecode,主要用来解码UIImage

SDWebImageManager

SDWebImageManager是SDWebImage的核心类,也是我们经常接触到的类,我们将一起看下是如何实现的

1. SDWebImageOptions

typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {/*** By default, when a URL fail to be downloaded, the URL is blacklisted so the library won't keep trying.* This flag disable this blacklisting.不会重新下载已经失败过的图片*/SDWebImageRetryFailed = 1 << 0,/*** By default, image downloads are started during UI interactions, this flags disable this feature,* leading to delayed download on UIScrollView deceleration for instance.*默认情况下,图像下载是在UI交互期间启动的,此标志禁用此功能,*导致延迟下载UIScrollView减速为例。*/SDWebImageLowPriority = 1 << 1,/*** This flag disables on-disk caching禁止在磁盘缓存,只在缓存中存在*/SDWebImageCacheMemoryOnly = 1 << 2,/*** This flag enables progressive download, the image is displayed progressively during download as a browser would do.* By default, the image is only displayed once completely downloaded.此标志支持逐行下载,图像在下载过程中逐步显示,就像浏览器所做的那样。*默认情况下,图像只显示一次,完全下载。*/SDWebImageProgressiveDownload = 1 << 3,/*** Even if the image is cached, respect the HTTP response cache control, and refresh the image from remote location if needed.* The disk caching will be handled by NSURLCache instead of SDWebImage leading to slight performance degradation.* This option helps deal with images changing behind the same request URL, e.g. Facebook graph api profile pics.* If a cached image is refreshed, the completion block is called once with the cached image and again with the final image.** Use this flag only if you can't make your URLs static with embedded cache busting parameter.任何图片都从新下载,不使用http cache,比如一个图片发送变化,但是url没有变化,用改options刷新数据*/SDWebImageRefreshCached = 1 << 4,/*** In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for* extra time in background to let the request finish. If the background task expires the operation will be cancelled.后台下载*/SDWebImageContinueInBackground = 1 << 5,/*** Handles cookies stored in NSHTTPCookieStore by setting* NSMutableURLRequest.HTTPShouldHandleCookies = YES;存储在cookie nshttpcookiestore*/SDWebImageHandleCookies = 1 << 6,/*** Enable to allow untrusted SSL certificates.* Useful for testing purposes. Use with caution in production.允许不信任的ssl证书*/SDWebImageAllowInvalidSSLCertificates = 1 << 7,/*** By default, images are loaded in the order in which they were queued. This flag moves them to* the front of the queue.默认情况下,图像按它们排队的顺序加载。这个标志是将图片放在队列的最前面*/SDWebImageHighPriority = 1 << 8,/*** 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,/*** We usually don't call transformDownloadedImage delegate method on animated images,* as most transformation code would mangle it.* Use this flag to transform them anyway.转换图像*/SDWebImageTransformAnimatedImage = 1 << 10,/*** 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默认情况下,image是在下载完成后加载,但是在一些情况下,我们想要在设置图像之前使用(例如应用过滤器或添加交叉淡入淡出动画),如果您想在成功完成时手动设置图像,请使用此标志*/SDWebImageAvoidAutoSetImage = 1 << 11,/*** By default, images are decoded respecting their original size. On iOS, this flag will scale down the* images to a size compatible with the constrained memory of devices.* If `SDWebImageProgressiveDownload` flag is set the scale down is deactivated.默认情况下,图像是进行解码的,这个标志是按比例缩小images的尺寸,来缩小占用的手机内存,如果` sdwebimageprogressivedownload `标志设置的情况下被停用。,压缩大的图片*/SDWebImageScaleDownLargeImages = 1 << 12
};

2. SDWebImageManagerDelegate

@protocol SDWebImageManagerDelegate <NSObject>@optional/*** Controls which image should be downloaded when the image is not found in the cache.** @param imageManager The current `SDWebImageManager`* @param imageURL     The url of the image to be downloaded** @return Return NO to prevent the downloading of the image on cache misses. If not implemented, YES is implied.//当缓存没有发现当前图片,那么会查看调用者是否实现改方法,如果return一个no,则不会继续下载这张图片*/
- (BOOL)imageManager:(nonnull SDWebImageManager *)imageManager shouldDownloadImageForURL:(nullable NSURL *)imageURL;/*** Allows to transform the image immediately after it has been downloaded and just before to cache it on disk and memory.* NOTE: This method is called from a global queue in order to not to block the main thread.** @param imageManager The current `SDWebImageManager`* @param image        The image to transform* @param imageURL     The url of the image to transform** @return The transformed image object.//当图片下载完成但是未添加到缓存里面,这时候调用该方法可以给图片旋转方向,注意是异步执行, 防止组织主线程*/
- (nullable UIImage *)imageManager:(nonnull SDWebImageManager *)imageManager transformDownloadedImage:(nullable UIImage *)image withURL:(nullable NSURL *)imageURL;@end

SDWebImageCompat

SDWebImage库中SDWebImageCompat是最基础的配置文件,为了兼容苹果各个平台。

SDWebImageCompat.h

#import <TargetConditionals.h>//不支持OC的GC内存管理
#ifdef __OBJC_GC__#error SDWebImage does not support Objective-C Garbage Collection
#endif//苹果的`TargetConditionals.h`文件有点怪,在所有平台上TARGET_OS_MAC都被定义了,所以只能通过TARGET_OS_IPHONE=0这种方式进行判断
#if !TARGET_OS_IPHONE && !TARGET_OS_IOS && !TARGET_OS_TV && !TARGET_OS_WATCH#define SD_MAC 1
#else#define SD_MAC 0
#endif//判断是否支持UIKIT, iOS 与 tvOS都支持。
#if TARGET_OS_IOS || TARGET_OS_TV#define SD_UIKIT 1
#else#define SD_UIKIT 0
#endif//是否是iOS系统
#if TARGET_OS_IOS#define SD_IOS 1
#else#define SD_IOS 0
#endif//是否是TV系统
#if TARGET_OS_TV#define SD_TV 1
#else#define SD_TV 0
#endif//是否是watchOS系统
#if TARGET_OS_WATCH#define SD_WATCH 1
#else#define SD_WATCH 0
#endif#if SD_MAC#import <AppKit/AppKit.h>#ifndef UIImage#define UIImage NSImage#endif#ifndef UIImageView#define UIImageView NSImageView#endif#ifndef UIView#define UIView NSView#endif
#else#if __IPHONE_OS_VERSION_MIN_REQUIRED != 20000 && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0#error SDWebImage doesn't support Deployment Target version < 5.0#endif#if SD_UIKIT#import <UIKit/UIKit.h>#endif#if SD_WATCH#import <WatchKit/WatchKit.h>#ifndef UIView#define UIView WKInterfaceObject#endif#ifndef UIImageView#define UIImageView WKInterfaceImage#endif#endif
#endif#ifndef NS_ENUM
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#endif#ifndef NS_OPTIONS
#define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
#endifFOUNDATION_EXPORT UIImage *SDScaledImageForKey(NSString *key, UIImage *image);typedef void(^SDWebImageNoParamsBlock)(void);FOUNDATION_EXPORT NSString *const SDWebImageErrorDomain;#ifndef dispatch_queue_async_safe
#define dispatch_queue_async_safe(queue, block)\if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(queue)) {\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

SDWebImageCompat.m

#import "SDWebImageCompat.h"
#import "UIImage+MultiFormat.h"//只能支持ARC
#if !__has_feature(objc_arc)#error SDWebImage is ARC only. Either turn on ARC for the project or use -fobjc-arc flag
#endif#if !OS_OBJECT_USE_OBJC#error SDWebImage need ARC for dispatch object
#endif//获取合适的scale的UIImage
inline UIImage *SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullable image) {if (!image) {return nil;}#if SD_MACreturn image;
#elif SD_UIKIT || SD_WATCHif ((image.images).count > 0) {NSMutableArray<UIImage *> *scaledImages = [NSMutableArray array];for (UIImage *tempImage in image.images) {[scaledImages addObject:SDScaledImageForKey(key, tempImage)];}UIImage *animatedImage = [UIImage animatedImageWithImages:scaledImages duration:image.duration];if (animatedImage) {animatedImage.sd_imageLoopCount = image.sd_imageLoopCount;}return animatedImage;} else {
#if SD_WATCHif ([[WKInterfaceDevice currentDevice] respondsToSelector:@selector(screenScale)]) {
#elif SD_UIKITif ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
#endifCGFloat scale = 1;if (key.length >= 8) {NSRange range = [key rangeOfString:@"@2x."];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;}return image;}
#endif
}NSString *const SDWebImageErrorDomain = @"SDWebImageErrorDomain";

sd_imageIndicator

图片下载loading的indicator,主要是这两个方法,这个属性也是需要开发者自己去设置的

//对属性sd_imageIndicator 加载indicator添加关联对象
- (id<SDWebImageIndicator>)sd_imageIndicator {return objc_getAssociatedObject(self, @selector(sd_imageIndicator));
}- (void)setSd_imageIndicator:(id<SDWebImageIndicator>)sd_imageIndicator {// 由于是之前添加了一个indicator,所以每次进来的时候//都需要移除之前的indicatorid<SDWebImageIndicator> previousIndicator = self.sd_imageIndicator;[previousIndicator.indicatorView removeFromSuperview];//重新设置关联对象sd_imageIndicatorobjc_setAssociatedObject(self, @selector(sd_imageIndicator), sd_imageIndicator, OBJC_ASSOCIATION_RETAIN_NONATOMIC);//在当前UIImageView/UIButton中添加indicatorView//这样就展示出indicatorView来了UIView *view = sd_imageIndicator.indicatorView;if (CGRectEqualToRect(view.frame, CGRectZero)) {view.frame = self.bounds;}// Center the indicator view
#if SD_MACCGPoint center = CGPointMake(NSMidX(self.bounds), NSMidY(self.bounds));NSRect frame = view.frame;view.frame = NSMakeRect(center.x - NSMidX(frame), center.y - NSMidY(frame), NSWidth(frame), NSHeight(frame));
#else//设置展示在当前的中心center位置view.center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
#endifview.hidden = NO;[self addSubview:view];
}

SDWebImage中已经为我们封装好了对应的类SDWebImageActivityIndicator,以及相应的方法,来实现对应的loading中的indicator效果只需要按照下面代码进行调用

//设置indicator方式为grayLargeIndicator,会显示一个大的灰色indicator
self.image.sd_imageIndicator = SDWebImageActivityIndicator.grayLargeIndicator

在SDWebImageActivityIndicator对应的分类中还有很多类型,下面是所有的类型

/// These indicator use the fixed color without dark mode support
/// gray-style activity indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *grayIndicator;
/// large gray-style activity indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *grayLargeIndicator;
/// white-style activity indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *whiteIndicator;
/// large white-style activity indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *whiteLargeIndicator;
/// These indicator use the system style, supports dark mode if available (iOS 13+/macOS 10.14+)
/// large activity indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *largeIndicator;
/// medium activity indicator
@property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *mediumIndicator;

UIImageView+WebCache层

面向UIImageView的是UIImageView+WebCache这个分类,将图片的URL,占位图片直接给这个类,下面是这个类的公共接口:

- (void)sd_setImageWithURL:(nullable NSURL *)url NS_REFINED_FOR_SWIFT;- (void)sd_setImageWithURL:(nullable NSURL *)urlplaceholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT;
- (void)sd_setImageWithURL:(nullable NSURL *)urlplaceholderImage:(nullable UIImage *)placeholderoptions:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;- (void)sd_setImageWithURL:(nullable NSURL *)urlplaceholderImage:(nullable UIImage *)placeholderoptions:(SDWebImageOptions)optionscontext:(nullable SDWebImageContext *)context;- (void)sd_setImageWithURL:(nullable NSURL *)urlcompleted:(nullable SDExternalCompletionBlock)completedBlock;- (void)sd_setImageWithURL:(nullable NSURL *)urlplaceholderImage:(nullable UIImage *)placeholdercompleted:(nullable SDExternalCompletionBlock)completedBlock NS_REFINED_FOR_SWIFT;- (void)sd_setImageWithURL:(nullable NSURL *)urlplaceholderImage:(nullable UIImage *)placeholderoptions:(SDWebImageOptions)optionscompleted:(nullable SDExternalCompletionBlock)completedBlock;- (void)sd_setImageWithURL:(nullable NSURL *)urlplaceholderImage:(nullable UIImage *)placeholderoptions:(SDWebImageOptions)optionsprogress:(nullable SDImageLoaderProgressBlock)progressBlockcompleted:(nullable SDExternalCompletionBlock)completedBlock;- (void)sd_setImageWithURL:(nullable NSURL *)urlplaceholderImage:(nullable UIImage *)placeholderoptions:(SDWebImageOptions)optionscontext:(nullable SDWebImageContext *)contextprogress:(nullable SDImageLoaderProgressBlock)progressBlockcompleted:(nullable SDExternalCompletionBlock)completedBlock;

其中这几个方法最终都会进入

- (void)sd_setImageWithURL:(nullable NSURL *)urlplaceholderImage:(nullable UIImage *)placeholderoptions:(SDWebImageOptions)optionscontext:(nullable SDWebImageContext *)contextprogress:(nullable SDImageLoaderProgressBlock)progressBlockcompleted:(nullable SDExternalCompletionBlock)completedBlock;

SDWebImageOptions,设置的图片加载以及缓存策略,有几种类型

typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {/**默认情况下,当一个URL下载失败的时候,这个URL会被加入黑名单列表,下次再有这个url的请求则停止请求。如果为true,这个值表示需要再尝试请求。*/SDWebImageRetryFailed = 1 << 0,/**默认情况下,当UI可以交互的时候就开始加载图片。这个标记可以阻止这个时候加载。而是当UIScrollView开始减速滑动的时候开始加载。*/SDWebImageLowPriority = 1 << 1,/**这个flag启动渐进式下载图像,类似浏览器加载图像那样逐步显示(从上倒下加载)*/SDWebImageProgressiveLoad = 1 << 2,/**一个图片缓存了,还是会重新请求.并且缓存侧略依据NSURLCache而不是SDImageCache。即在URL没变但是服务器图片发生更新时使用,这时我们需要在NSMutableRequest中设置上(If-Modified-Since-其实是缓存的最后修改时间,有后台返回),这个参数是在上一次网络请求之后,NSResponse中的Last-Modified获取,并保存下载,在下次发送网络请求的时候添加到请求头中;这样当我们下载同一张照片的时候,其实是拿取的上次GET请求的NSURLCache缓存中的图片,并且如果后台发生变化会重新请求图片*/SDWebImageRefreshCached = 1 << 3,/**启动后台下载,实现原理是通过向系统询问后台的额外时间来完成请求的。 如果后台任务到期,则操作将被取消*/SDWebImageContinueInBackground = 1 << 4,/**当设置了NSMutableURLRequest.HTTPShouldHandleCookies = YES时,可以控制存储NSHTTPCookieStorage中的cookie*/SDWebImageHandleCookies = 1 << 5,/**允许不安全的SSL证书,用于测试环境,在正式环境中谨慎使用*/SDWebImageAllowInvalidSSLCertificates = 1 << 6,/**默认情况下,image在加载的时候是按照他们在队列中的顺序装载的(就是先进先出)。这个flag会把他们移动到队列的前端,并且立刻装载,而不是等到当前队列装载的时候再装载。*/SDWebImageHighPriority = 1 << 7,/**默认情况下,占位图会在图片下载的时候显示.这个flag开启会延迟占位图显示的时间,等到图片下载完成之后才会显示占位图.*/SDWebImageDelayPlaceholder = 1 << 8,/**一般不会在动画图片上调用 transformDownloadedImage 代理方法,这样不能够管理动画图片这个flag为尝试转换动画图片*/SDWebImageTransformAnimatedImage = 1 << 9,/**图片在下载后被加载到imageView。这个flag避免自动设置图片,来手动设置一下图片(引用一个滤镜或者加入透入动画)*/SDWebImageAvoidAutoSetImage = 1 << 10,/**默认情况下,图像将根据其原始大小进行解码。 在iOS上,此flat会将图片缩小到与设备的受限内存兼容的大小。    但如果设置了SDWebImageAvoidDecodeImage则此flat不起作用。 如果设置了SDWebImageProgressiveLoad它将被忽略*/SDWebImageScaleDownLargeImages = 1 << 11,/**结合SDWebImageQueryMemoryData设置同步查询图像数据(一般不建议这么使用,除非是在同一个runloop里避免单元格复用时发生闪现)*/SDWebImageQueryMemoryData = 1 << 12,/**结合SDWebImageQueryMemoryData设置同步查询图像数据(一般不建议这么使用,除非是在同一个runloop里避免单元格复用时发生闪现)*/SDWebImageQueryMemoryDataSync = 1 << 13,/**如果内存查询没有的时候,强制同步磁盘查询(这三个查询可以组合使用,一般不建议这么使用,除非是在同一个runloop里避免单元格复用时发生闪现)*/SDWebImageQueryDiskDataSync = 1 << 14,/*** 默认情况下,当缓存丢失时,SD将从网络下载图像。 此flat可以防止这样,使其仅从缓存加载。*/SDWebImageFromCacheOnly = 1 << 15,/*** 默认情况下,SD在下载之前先从缓存中查找,此flat可以防止这样,使其仅从网络下载*/SDWebImageFromLoaderOnly = 1 << 16,/*** 默认情况下,SD在图像加载完成后使用SDWebImageTransition进行某些视图转换,此转换仅适用于从网络下载图像。 此flat可以强制为内存和磁盘缓存应用视图转换。*/SDWebImageForceTransition = 1 << 17,/**默认情况下,SD在查询缓存和从网络下载时会在后台解码图像,这有助于提高性能,因为在屏幕上渲染图像时,需要首先对其进行解码。这发生在Core Animation的主队列中。然而此过程也可能会增加内存使用量。如果由于过多的内存消耗而遇到问题,可以用此flat禁止解码图像。*/SDWebImageAvoidDecodeImage = 1 << 18,/*** 默认情况下,SD会解码动画图像,该flat强制只解码第一帧并生成静态图。*/SDWebImageDecodeFirstFrameOnly = 1 << 19,/**默认情况下,对于SDAnimatedImage,SD会在渲染过程中解码动画图像帧以减少内存使用量。 但是用户可以指定将所有帧预加载到内存中,以便在大量imageView共享动画图像时降低CPU使用率。这实际上会在后台队列中触发preloadAllAnimatedImageFrames(仅限磁盘缓存和下载)。*/SDWebImagePreloadAllFrames = 1 << 20
};

还有一个变量是SDWebImageContext *context,可以看到SDWebImageContext 其实就是以 SDWebImageContextOptionkeyid(指定类型或者协议)为valueNSDictionary


http://chatgpt.dhexx.cn/article/FrFbBgvf.shtml

相关文章

开源框架:SDWebImage

引言: SDWebImage是我搞iOS以来少数佩服的框架,膜拜一下作者.真的写的非常棒! 这套开源框架还是蛮重要的, 涉及到异步加载图片源和自动缓存. 我们如果能够熟练使用其API 就可以实现很多复杂的需求了. 作者依旧在更新,目前3.0 版本已经非常强大! 简化了更多的API接口.加强了…

iOS 第三方框架-SDWebImage解读

在iOS的图片加载框架中&#xff0c;SDWebImage可谓是占据大半壁江山。它支持从网络中下载且缓存图片&#xff0c;并设置图片到对应的UIImageView控件或者UIButton控件。在项目中使用SDWebImage来管理图片加载相关操作可以极大地提高开发效率&#xff0c;让我们更加专注于业务逻…

iOS——SDWebImage解读

前言 在iOS的图片加载框架中&#xff0c;SDWebImage占据了大半壁江山。它提供了UIImageView的一个分类&#xff0c;支持从网络中下载且缓存图片&#xff0c;并设置图片到对应的UIImageView控件或者UIButton控件。在项目中使用SDWebImage来管理图片加载相关操作可以极大地提高开…

SDWebImage异步加载图片及缓存的管理与清理

一、SDWebImage介绍 1、在项目的开发过程中&#xff0c;我们经常会用到异步加载图片的功能&#xff0c;先从网络上异步下载图片&#xff0c;然后通过UIImageView显示在屏幕上。这是一个经常使用的功能&#xff0c;基本上所有的联网应用程序都要用到的功能&#xff0c;现在GitH…

iOS SDWebImage详细介绍

在iOS的图片加载框架中&#xff0c;SDWebImage使用频率非常高。它支持从网络中下载且缓存图片&#xff0c;并设置图片到对应的UIImageView控件或者UIButton控件。在项目中使用SDWebImage来管理图片加载相关操作可以极大地提高开发效率&#xff0c;让我们更加专注于业务逻辑实现…

JNA入门

1&#xff0c;什么是JNA&#xff1f; JNA全称Java Native Access&#xff0c;是一个建立在JNI技术之上的Java开源框架。 2&#xff0c;JNA有什么用&#xff1f; Java开发过程中&#xff0c;有时候会需要和C&#xff0c;C等交互&#xff0c;JNA相当于中间的适配器 3&#xf…

JNA —— Java调用C/C++动态库

工作所需&#xff0c;要使用Java调用c/c的动态库&#xff0c;实现Java程序使用动态库中的函数。 搜索了一番&#xff0c;常用的有JNI、JNA方法。 JNI&#xff08;Java Native Interface&#xff09; JNI定义了一种公用的语法&#xff0c;当Java和c/c都遵循这样的语法时就可以互…

关于JAVA中的JNA

1、jna是什么 jna是java native access的简称&#xff0c;用他可以调用C、C代码&#xff0c;特别是windows中强大的库文件&#xff08;dll&#xff0c;在linux下是so文件&#xff09;&#xff0c;这样java就可以操控底层的一些东西&#xff0c;比如调用加密机、智能卡之类的 2、…

JNA与JNI谁更受青睐呢

JNA(Java Native Access)框架是一个开源的Java框架&#xff0c;是SUN公司主导开发的&#xff0c;建立在经典的JNI的基础之上的一个框架。非常强大、易用。其中JNA是对JNI的封装&#xff0c;能让java使用者更好的使用本地的动态库 一、JNA与JNI的比较 JNI: JNI允许Java代码和其…

JNA实战系列:第一个简单的JNA开发程序

文章目录 第一个简单的JNA的开发程序一、引入依赖包二、创建一个接口&#xff0c;继承Libary类三、在Java中使用dll中封装的方法总结:JNA中调用C、CDLL或者.so库中的函数的步骤总结:思考 第一个简单的JNA的开发程序 假如有一个helloworld.h和一个helloworld.dll文件&#xff0…

Java通过JNA调用so库 Linux环境

记录一下自己的JNA调研成果&#xff0c;需求是公司同事用C写了一个红外测温SDK&#xff0c;编译成so文件后提供给客户使用。客户需要一个Linux环境用Java调用so库的一个demo&#xff0c;刚好就我一个懂点Java&#xff0c;所有有了这次调研。 因为JNA相关资料实在太少&#xff…

JNI便捷开发框架JNA框架之入门(一)

一、JNA介绍 JNA(Java Native Access)框架是一个开源的Java框架&#xff0c;是SUN公司主导开发的&#xff0c;建立在经典的JNI的基础之上的一个框架。它提供一组Java工具类用于在运行期动态访问系统本地共享类库而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中…

JNA简介

2019独角兽企业重金招聘Python工程师标准>>> JNA JNA&#xff08;Java Native Access &#xff09;提供一组Java工具类用于在运行期动态访问系统本地库&#xff08;native library&#xff1a;如Window的dll&#xff09;而不需要编写任何Native/JNI代码。开发人员只…

JNA的概念

1. JNA简单介绍 先说JNI(Java Native Interface)吧&#xff0c;有过不同语言间通信经历的一般都知道&#xff0c;它允许Java代码和其他语言&#xff08;尤其C/C&#xff09;写的代码进行交互&#xff0c;只要遵守调用约定即可。首先看下JNI调用C/C的过程&#xff0c;注意写程序…

Java 之 JNA(调用第三方库)

是什么&#xff1f; 一、了解JNA之前&#xff0c;我们先了解一下JNA的前身JNI&#xff08;Java Native Interface&#xff09;&#xff1a;通过使用 Java本地接口书写程序&#xff0c;可以确保代码在不同的平台上方便移植。 [1] 从Java1.1开始&#xff0c;JNI标准成为java平台…

JNA实战笔记汇总(一)—— JNA简介及demo环境创建

目录 1、简介 2、原理 3、配置环境&#xff0c;创建demo 3.1 搞清楚.dll/.so文件适用环境 3.2 创建一个普通的maven项目 3.2.1 将.dll/.so文件放在resources根路径下 3.2.2 pom.xml文件添加jna依赖 3.2.3 编写一个CLibrary接口&#xff0c;继承Library接口 3.2.4 编写…

ROW(行)与COLUMN(列)

数列数&#xff0c;COLUMNS&#xff08;A:B&#xff09;2&#xff0c;即A到B一共两列。

column函数HTML5,column函数 excel中column函数的使用方法

column函数是一种查询的工具,我相信许多人都不会使用到这一个函数,因此在实际工程当中并不是十分的常见,然而这一款韩束如果能够掌握,对我们的工作也是非常有帮助的,接下来我们就一起来好好的了解一下这个函数究竟该如何使用。 column函数——column函数的使用方法 1.colu…

Duplicate column name ‘xxx_column‘

错误场景: 使用MyBatisPlus分页查询的情况下列名重复(注:select查询不报错, 映射正常) 例如 → select id, name, name from user 解决方法: 列名重复&#xff0c;删除重复的列名, 保证留一个就可以了 错误原因: 根据错误定位到PaginationInterceptor的queryTotal方法 最终…

mysql插入报错:colum xxx cannot be null

测试同学催促我赶紧解决上面的问题&#xff0c;首先看了下数据库这个字段确实是必填的&#xff0c;默认是当前时间 可是看了下代码发现mybatis的sql语句插入的时候包含了这个operate_time字段 那么讲道理必需给实体对象的operateTime字段赋值才行&#xff0c;可线上代码明明没有…