版本:4.4.8
UIImageView+WebCache.h
@interface UIImageView (WebCache)
//加载url图像
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock;
//placeholder 占位符 url图像还未加载完成时使用
//options 配置
typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
//默认情况下,当URL下载失败时,该URL被列入黑名单,因此该库将不会继续尝试。
//此标志禁用此黑名单。
SDWebImageRetryFailed = 1 << 0,
//默认情况下,图片下载是在用户界面交互过程中开始的,可能导致操作卡顿
//此标志会禁用此功能,
SDWebImageLowPriority = 1 << 1,
//默认情况下,会同时缓存在内存和磁盘
//此标志禁用磁盘缓存,仅缓存在内存中
SDWebImageCacheMemoryOnly = 1 << 2,
//默认情况下,仅在完全下载后才显示图像
//该标志启用渐进式下载,在下载过程中图像会像浏览器一样逐步显示。
SDWebImageProgressiveDownload = 1 << 3,
//默认情况下,会优先从缓存获取图像
//该标志则不从缓存获取,并在获取成功后刷新缓存
//适用于获取QQ微信头像这类操作
SDWebImageRefreshCached = 1 << 4,
//默认情况下,进入后台后暂停下载
//该标志则在应用程序进入后台时,则继续下载图像。
//在后台增加时间以使请求完成。如果后台任务到期,则该操作将被取消。
SDWebImageContinueInBackground = 1 << 5,
//通过设置NSMutableURLRequest.HTTPShouldHandleCookies = YES
//处理存储在NSHTTPCookieStore中的cookie。
SDWebImageHandleCookies = 1 << 6,
//启用以允许不受信任的SSL证书。
//用于测试目的。在生产中请谨慎使用。
SDWebImageAllowInvalidSSLCertificates = 1 << 7,
//默认情况下,图像按排队顺序加载。
//此标志将它们移至队列的最前面。
SDWebImageHighPriority = 1 << 8,
//默认情况下,占位符图像在加载图像时加载。
//此标志将延迟占位符图像的加载,直到图像完成加载为止。
SDWebImageDelayPlaceholder = 1 << 9,
//默认情况下,我们通常不对动画图像调用transformDownloadedImage委托方法
//因为大多数转换代码都会破坏它。
//此标志对其进行转换。
SDWebImageTransformAnimatedImage = 1 << 10,
//默认情况下,下载后将图像添加到imageView中。
//如果要在成功时手动在完成时设置图像,请使用此标志。
SDWebImageAvoidAutoSetImage = 1 << 11,
//默认情况下,图像会按照原始尺寸进行解码。
//在iOS上,此标志会将图像缩小到与设备的受限内存兼容的大小。
//如果设置了“ SDWebImageProgressiveDownload”标志,则缩小比例无效。
SDWebImageScaleDownLargeImages = 1 << 12,
//默认情况下,当映像缓存在内存中时,我们不查询磁盘数据。
//此标志可以强制同时查询磁盘数据。
//建议与SDWebImageQueryDiskSync一起使用此标志,以确保将映像加载到同一runloop中。
SDWebImageQueryDataWhenInMemory = 1 << 13,
//默认情况下,我们同步查询内存缓存,异步查询磁盘缓存。
//此标志可以强制同步查询磁盘缓存,以确保将映像加载到同一runloop中。
//如果禁用内存缓存或在其他情况下,此标志可以避免在cell重用期间闪烁。
SDWebImageQueryDiskSync = 1 << 14,
//默认情况下,当缓存丢失时,将从网络下载映像。
//该标志可以防止从网络而仅从缓存加载。
SDWebImageFromCacheOnly = 1 << 15,
//默认情况下,当您使用“ SDWebImageTransition”在图像加载完成后进行某些视图转换时,此转换仅适用于从网络下载图像。
//此标志也可以强制将视图转换应用于内存和磁盘缓存。
SDWebImageForceTransition = 1 << 16
};
//progressBlock 下载进度block
//receivedSize 已接收到的大小 expectedSize 预计大小 targetURL 图像的url
typedef void(^SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL);
//completedBlock 下载完成block
//image 下载成功后的image error 下载失败的错误,不为空时,image为空
//cacheType 图像获取类型 imageURL 图像的url
typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL);
//cacheType
typedef NS_ENUM(NSInteger, SDImageCacheType) {
//该图片不适用于SDWebImage缓存,但已从Web下载。
SDImageCacheTypeNone,
//该映像是从磁盘缓存中获取的。
SDImageCacheTypeDisk,
//该图像是从内存缓存中获取的。
SDImageCacheTypeMemory
};
//加载图像 将最终跳转到上面的方法
- (void)sd_setImageWithURL:(nullable NSURL *)url NS_REFINED_FOR_SWIFT;
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT;
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;
- (void)sd_setImageWithURL:(nullable NSURL *)url
completed:(nullable SDExternalCompletionBlock)completedBlock;
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
completed:(nullable SDExternalCompletionBlock)completedBlock
- (void)sd_setImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDExternalCompletionBlock)completedBlock;
//已弃用 优先从缓存获取图像并放在占位符上
- (void)sd_setImageWithPreviousCachedImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock __deprecated_msg("This method is misunderstanding and deprecated, consider using `SDWebImageQueryDiskSync` options with `sd_setImageWithURL:` instead");
//加载全部url并组合为动图
- (void)sd_setAnimationImagesWithURLs:(nonnull NSArray<NSURL *> *)arrayOfURLs;
//取消动图的加载
- (void)sd_cancelCurrentAnimationImagesLoad;
@end
例1:
self.baseImageView = [[UIImageView alloc] init];
[self.view addSubview:self.baseImageView];
[self.baseImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
[self.baseImageView sd_setImageWithURL:[NSURL URLWithString:@"https://iknow-pic.cdn.bcebos.com/c83d70cf3bc79f3d6e7bf85db8a1cd11738b29c0"]
placeholderImage:nil options:SDWebImageRetryFailed
progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
NSLog(@"%.2f%%", receivedSize*100.0/expectedSize);
} completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
if (image) {
NSLog(@"completed");
}
}];
输出:
2020-06-10 14:11:11.039099+0800 SDWebImageDemo[8175:219247] -0.00%
2020-06-10 14:11:11.323848+0800 SDWebImageDemo[8175:219246] 0.00%
2020-06-10 14:11:11.324144+0800 SDWebImageDemo[8175:219246] 47.62%
2020-06-10 14:11:11.346725+0800 SDWebImageDemo[8175:219247] 96.73%
2020-06-10 14:11:11.348076+0800 SDWebImageDemo[8175:219244] 100.00%
2020-06-10 14:11:11.371333+0800 SDWebImageDemo[8175:219016] completed
例2:
self.animateImageView = [[UIImageView alloc] init];
[self.view addSubview:self.animateImageView];
[self.animateImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.baseImageView.mas_bottom).offset(50);
make.left.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
NSArray *urls = @[[NSURL URLWithString:@"https://iknow-pic.cdn.bcebos.com/c83d70cf3bc79f3d6e7bf85db8a1cd11738b29c0"],
[NSURL URLWithString:@"https://b-ssl.duitang.com/uploads/item/201507/04/20150704212949_PSfNZ.jpeg"],
[NSURL URLWithString:@"https://wx3.sinaimg.cn/orj360/6987953cly1g9kbs5d56ij20k024sh2w.jpg"]];
[self.animateImageView sd_setAnimationImagesWithURLs:urls];
效果如下图:
123.gif
UIImageView+HighlightedWebCache.h
@interface UIImageView (HighlightedWebCache)
//用法如UIImageView+WebCache.h
//但设置的是UIImageView的highlightedImage
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url NS_REFINED_FOR_SWIFT;
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
completed:(nullable SDExternalCompletionBlock)completedBlock
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
completed:(nullable SDExternalCompletionBlock)completedBlock;
- (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock;
@end
例:
self.baseImageView = [[UIImageView alloc] init];
[self.view addSubview:self.baseImageView];
[self.baseImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
[self.baseImageView sd_setImageWithURL:[NSURL URLWithString:@"https://iknow-pic.cdn.bcebos.com/c83d70cf3bc79f3d6e7bf85db8a1cd11738b29c0"]];
[self.baseImageView sd_setHighlightedImageWithURL:[NSURL URLWithString:@"https://b-ssl.duitang.com/uploads/item/201507/04/20150704212949_PSfNZ.jpeg"]];
效果如下 点击切换时执行[self.baseImageView setHighlighted:!self.baseImageView.isHighlighted];
123.gif
UIButton+WebCache.h
@interface UIButton (WebCache)
#pragma mark - Image
//当前按钮当前状态的url
//若为空 返回UIControlStateNormal状态的url
- (nullable NSURL *)sd_currentImageURL;
//返回按钮对应状态的url
- (nullable NSURL *)sd_imageURLForState:(UIControlState)state;
//在对应状态的按钮上添加url图像
- (void)sd_setImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state NS_REFINED_FOR_SWIFT;
- (void)sd_setImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT;
- (void)sd_setImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;
- (void)sd_setImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
completed:(nullable SDExternalCompletionBlock)completedBlock;
- (void)sd_setImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
completed:(nullable SDExternalCompletionBlock)completedBlock
//以上方法最终都会调用该方法
- (void)sd_setImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDExternalCompletionBlock)completedBlock;
#pragma mark - Background Image
//用法与上面一致 只不过对向从UIButton.image 变成了UIButton.backgroundImage
- (nullable NSURL *)sd_currentBackgroundImageURL;
- (nullable NSURL *)sd_backgroundImageURLForState:(UIControlState)state;
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state NS_REFINED_FOR_SWIFT;
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT;
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
completed:(nullable SDExternalCompletionBlock)completedBlock;
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
completed:(nullable SDExternalCompletionBlock)completedBlock
- (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
forState:(UIControlState)state
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
completed:(nullable SDExternalCompletionBlock)completedBlock;
#pragma mark - Cancel
//取消UIButton.image的图像加载
- (void)sd_cancelImageLoadForState:(UIControlState)state;
//取消UIButton.backgroundImage的图像加载
- (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state;
@end
例:
self.baseImageButton = [UIButton buttonWithType:UIButtonTypeCustom];
[self.view addSubview:self.baseImageButton];
[self.baseImageButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
[self.baseImageButton sd_setImageWithURL:[NSURL URLWithString:@"https://iknow-pic.cdn.bcebos.com/c83d70cf3bc79f3d6e7bf85db8a1cd11738b29c0"] forState:UIControlStateNormal];
[self.baseImageButton sd_setBackgroundImageWithURL:[NSURL URLWithString:@"https://b-ssl.duitang.com/uploads/item/201507/04/20150704212949_PSfNZ.jpeg"] forState:UIControlStateNormal];
[self.baseImageButton setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 150)];
效果如下
image.png
UIView+WebCache.h
@interface UIView (WebCache)
//获取当前图像的URL。
//请注意,由于类别的限制,如果直接使用setImage:,则此属性可能会不同步。
- (nullable NSURL *)sd_imageURL;
//与视图关联的当前图像加载进度。单位数是接收的大小和下载的例外大小。
//新的图像加载开始(从当前队列更改)后,“ totalUnitCount”和“ completedUnitCount”将重置为0。
//如果未调用progressBlock但图像加载成功以指示进度已完成(从主队列更改),则将它们设置为“ SDWebImageProgressUnitCountUnknown”。
@property (nonatomic, strong, null_resettable) NSProgress *sd_imageProgress;
//加载图像
//[imageView sd_setImageWithURL:] [button sd_setBackgroundImageWithURL:forState:]最终会调用该方法
- (void)sd_internalSetImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
operationKey:(nullable NSString *)operationKey
setImageBlock:(nullable SDSetImageBlock)setImageBlock
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock;
- (void)sd_internalSetImageWithURL:(nullable NSURL *)url
placeholderImage:(nullable UIImage *)placeholder
options:(SDWebImageOptions)options
operationKey:(nullable NSString *)operationKey
setImageBlock:(nullable SDSetImageBlock)setImageBlock
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDExternalCompletionBlock)completedBlock
context:(nullable NSDictionary<NSString *, id> *)context;
//operationKey 操作类型
//[UIImageView sd_setHighlightedImageWithURL:]就对应UIImageViewImageOperationHighlighted
//setImageBlock 设置图像block
//image 下载好的图像 imageData 下载好的图像数据
//需要在该回调中设置view的image
typedef void(^SDSetImageBlock)(UIImage * _Nullable image, NSData * _Nullable imageData);
//progressBlock 下载进度block
//completedBlock 下载完成block
//context
//取消当前图像的加载
- (void)sd_cancelCurrentImageLoad;
#pragma mark - Image Transition
//图像加载完成后的图像显示的过渡。
@property (nonatomic, strong, nullable) SDWebImageTransition *sd_imageTransition;
#pragma mark - Activity indicator
//设置菊花的显示
- (void)sd_setShowActivityIndicatorView:(BOOL)show;
//菊花的style
- (void)sd_setIndicatorStyle:(UIActivityIndicatorViewStyle)style;
//获取菊花的显示状态
- (BOOL)sd_showActivityIndicatorView;
//该视图上添加菊花
- (void)sd_addActivityIndicator;
//该视图上移除菊花
- (void)sd_removeActivityIndicator;
@end
例:
self.baseImageView = [[UIImageView alloc] init];
self.baseImageView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:self.baseImageView];
[self.baseImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
__weak typeof(self) weakSelf = self;
[UIActivityIndicatorView appearance].color = [UIColor redColor];
//这两句代码效果相同 都是在加载时转菊花 SDWebImage会在加载完成后自动移除菊花
// [self.baseImageView sd_addActivityIndicator];
[self.baseImageView sd_setShowActivityIndicatorView:YES];
[self.baseImageView sd_internalSetImageWithURL:[NSURL URLWithString:@"https://nokiatech.github.io/heif/content/images/ski_jump_1440x960.heic"]
placeholderImage:nil options:SDWebImageRetryFailed operationKey:nil
setImageBlock:^(UIImage * _Nullable image, NSData * _Nullable imageData) {
//需要手动在该回调中设置image
weakSelf.baseImageView.image = image;
} progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
NSLog(@"%.2f%%", receivedSize*100.0/expectedSize);
} completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
if (image) {
NSLog(@"completed");
}
} context:nil];
效果如下
加载时
image.png
加载完成后
image.png
UIView+WebCacheOperation.h
这些方法用于支持取消UIView图像加载,它设计为内部使用,而不是外部使用。
@interface UIView (WebCacheOperation)
//设置图像加载的操作(存储在基于UIView的弱映射表中)
//会先取消并移除同key的操作再新增
//key为sd_internalSetImageWithURL方法中的operationKey 若为空 则为[self class]
- (void)sd_setImageLoadOperation:(nullable id<SDWebImageOperation>)operation forKey:(nullable NSString *)key;
//取消并移除对应Key的操作
- (void)sd_cancelImageLoadOperationWithKey:(nullable NSString *)key;
//移除对应Key的操作
- (void)sd_removeImageLoadOperationWithKey:(nullable NSString *)key;
@end
SDWebImageTransition.h
@interface SDWebImageTransition : NSObject
//默认情况下,将在动画开始时设置view的image。
//默认为NO 为YES时需要去自定义设置图像
@property (nonatomic, assign) BOOL avoidAutoSetImage;
//过渡动画的持续时间,以秒为单位。默认值为0.5。
@property (nonatomic, assign) NSTimeInterval duration;
//用于此过渡动画中所有动画的计时功能(macOS专用)
@property (nonatomic, strong, nullable) CAMediaTimingFunction *timingFunction NS_AVAILABLE_MAC(10_7);
//动画类型 UIViewAnimationOptions
@property (nonatomic, assign) SDWebImageAnimationOptions animationOptions;
//动画开始之前执行的回调
@property (nonatomic, copy, nullable) SDWebImageTransitionPreparesBlock prepares;
//prepares
typedef void (^SDWebImageTransitionPreparesBlock)(__kindof UIView * _Nonnull view,
UIImage * _Nullable image, NSData * _Nullable imageData, SDImageCacheType cacheType,
NSURL * _Nullable imageURL);
//动画时的回调
@property (nonatomic, copy, nullable) SDWebImageTransitionAnimationsBlock animations;
//animations
typedef void (^SDWebImageTransitionAnimationsBlock)(__kindof UIView * _Nonnull view,
UIImage * _Nullable image);
//动画完成后的回调
@property (nonatomic, copy, nullable) SDWebImageTransitionCompletionBlock completion;
//completion
typedef void (^SDWebImageTransitionCompletionBlock)(BOOL finished);
@end
@interface SDWebImageTransition (Conveniences)
//已经定义好的过渡效果
///淡入淡出过渡。
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *fadeTransition;
///从左侧翻转过渡。
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *flipFromLeftTransition;
///从右侧翻转过渡。
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *flipFromRightTransition;
///从上方翻转过渡。
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *flipFromTopTransition;
///从下方翻转过渡。
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *flipFromBottomTransition;
///卷曲过渡。
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *curlUpTransition;
///向下卷曲过渡。
@property (nonatomic, class, nonnull, readonly) SDWebImageTransition *curlDownTransition;
//和上面属性对应的类方法
+ (nonnull instancetype)fadeTransition;
+ (nonnull instancetype)flipFromLeftTransition;
+ (nonnull instancetype)flipFromRightTransition;
+ (nonnull instancetype)flipFromTopTransition;
+ (nonnull instancetype)flipFromBottomTransition;
+ (nonnull instancetype)curlUpTransition;
+ (nonnull instancetype)curlDownTransition;
@end
例:
self.baseImageView = [[UIImageView alloc] init];
self.baseImageView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:self.baseImageView];
[self.baseImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
__weak typeof(self) weakSelf = self;
[UIActivityIndicatorView appearance].color = [UIColor redColor];
//这两句代码效果相同 都是在加载时转菊花 SDWebImage会在加载完成后自动移除菊花
// [self.baseImageView sd_addActivityIndicator];
[self.baseImageView sd_setShowActivityIndicatorView:YES];
SDWebImageTransition *transition = [SDWebImageTransition new];
//以下三种写法效果相同
transition = SDWebImageTransition.flipFromTopTransition;
// transition = [SDWebImageTransition flipFromTopTransition];
// transition.animationOptions = UIViewAnimationOptionTransitionFlipFromTop | UIViewAnimationOptionAllowUserInteraction;
self.baseImageView.sd_imageTransition = transition;
[self.baseImageView sd_internalSetImageWithURL:[NSURL URLWithString:@"https://nokiatech.github.io/heif/content/images/ski_jump_1440x960.heic"]
placeholderImage:nil options:SDWebImageRetryFailed operationKey:nil
setImageBlock:^(UIImage * _Nullable image, NSData * _Nullable imageData) {
//需要手动在该回调中设置image
weakSelf.baseImageView.image = image;
} progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
NSLog(@"%.2f%%", receivedSize*100.0/expectedSize);
} completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
if (image) {
NSLog(@"completed");
}
} context:nil];
效果如下
123.gif
UIImage+GIF.h
@interface UIImage (GIF)
//将data转换成动图
//若data为静图的数据 若使用此方法 加载会变慢
//请使用[UIImage imageWithData:]或[UIImage sd_imageWithDataWithData:]
+ (UIImage *)sd_animatedGIFWithData:(NSData *)data;
//当前image是否为gif
- (BOOL)isGIF;
@end
例:
self.animateImageView = [[UIImageView alloc] init];
[self.view addSubview:self.animateImageView];
[self.animateImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
//本地动图
// NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"dong" ofType:@"gif"];
// NSData *imageData = [NSData dataWithContentsOfFile:imagePath];
// UIImage *image = [UIImage sd_animatedGIFWithData:imageData];
// self.animateImageView.image = image;
//网络动图
__weak typeof(self) weakSelf = self;
[self.animateImageView sd_internalSetImageWithURL:[NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1591247443713&di=3fbe0d6527c3f6f2a99cdae6a980faf0&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20171228%2F1c446e1cd30e43c3a1fa08c83020617d.gif"]
placeholderImage:nil options:SDWebImageRetryFailed operationKey:nil
setImageBlock:^(UIImage * _Nullable image, NSData * _Nullable imageData) {
//可用以下两种方式获取图像格式
SDImageFormat format = image.sd_imageFormat;
// SDImageFormat format = [NSData sd_imageFormatForImageData:imageData];
if (format == SDImageFormatGIF) {
//若为gif
weakSelf.animateImageView.image = [UIImage sd_animatedGIFWithData:imageData];
} else {
//不为gif时 使用sd_imageWithDataWithData或imageWithData
weakSelf.animateImageView.image = [UIImage sd_imageWithData:imageData];
// weakSelf.animateImageView.image = [UIImage imageWithData:imageData];
}
} progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
} completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
if (weakSelf.animateImageView.image.isGIF) {
NSLog(@"gif");
}
}];
效果如下
123.gif
NSData+ImageContentType.h
@interface NSData (ImageContentType)
//返回该数据的图像格式
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
//图像格式类型
typedef NS_ENUM(NSInteger, SDImageFormat) {
SDImageFormatUndefined = -1,
SDImageFormatJPEG = 0,
SDImageFormatPNG,
SDImageFormatGIF,
SDImageFormatTIFF,
SDImageFormatWebP,
SDImageFormatHEIC,
SDImageFormatHEIF
};
//将SDImageFormat转换成UTTyppe
//UTTyppe用于ImageIO
+ (nonnull CFStringRef)sd_UTTypeFromSDImageFormat:(SDImageFormat)format;
//将UTTyppe转换成SDImageFormat
+ (SDImageFormat)sd_imageFormatFromUTType:(nonnull CFStringRef)uttype;
@end
UIImage+MultiFormat.h
@interface UIImage (MultiFormat)
//循环计数
//对于静态图像格式,此值始终为0。
//对于动画图像格式,0表示无限循环。
@property (nonatomic, assign) NSUInteger sd_imageLoopCount;
//图像格式
//如果您没有手动指定格式,则使用CGImageGetUTType(self.CGImage)检索此信息
//对于非基于CG的图像,该信息可能返回nil。将返回“ SDImageFormatUndefined”作为默认值。
@property (nonatomic, assign) SDImageFormat sd_imageFormat;
//将data转换成图像 不支持动图
//动图请使用sd_animatedGIFWithData:
+ (nullable UIImage *)sd_imageWithData:(nullable NSData *)data;
//获取当前图像的数据 格式为SDImageFormatUndefined
- (nullable NSData *)sd_imageData;
//获取当前图像对应格式的数据
- (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat;
SDWebImageCoder.h
//这是提供自定义图像解码/编码的图像编码器协议。
@protocol SDWebImageCoder <NSObject>
@required
#pragma mark - Decoding
//如果编码器可以解码这些数据,则返回YES。否则,数据应传递给另一个编码器。
- (BOOL)canDecodeFromData:(nullable NSData *)data;
//将数据解码为图像。
- (nullable UIImage *)decodedImageWithData:(nullable NSData *)data;
//用原始图像和图像数据的地址解压缩图像。
//optionsDict 传入@{SDWebImageCoderScaleDownLargeImagesKey:@"YES"}来缩小大图
- (nullable UIImage *)decompressedImageWithImage:(nullable UIImage *)image
data:(NSData * _Nullable * _Nonnull)data
options:(nullable NSDictionary<NSString*, NSObject*>*)optionsDict;
#pragma mark - Encoding
//如果编码器可以编码该图像格式的图像,则返回YES。否则,应将其传递给另一个编码器。
- (BOOL)canEncodeToFormat:(SDImageFormat)format;
//将该图像格式的图像编码为数据。
- (nullable NSData *)encodedDataWithImage:(nullable UIImage *)image format:(SDImageFormat)format;
@end
//这是提供自定义渐进式图像解码的图像编码器协议。
@protocol SDWebImageProgressiveCoder <SDWebImageCoder>
@required
//如果编码器可以增量解码这些数据,则返回YES。否则,应将其传递给另一个编码器。
- (BOOL)canIncrementallyDecodeFromData:(nullable NSData *)data;
//将图像数据增量解码为图像。
//data 已下载的图像数据
//finished 下载是否完成
//警告,因为增量解码需要保留解码后的上下文,所以我们将为每个下载操作分配一个具有相同类的新实例,以避免冲突
- (nullable UIImage *)incrementallyDecodedImageWithData:(nullable NSData *)data finished:(BOOL)finished;
@end
SDWebImageCoderHelper.h
@interface SDWebImageCoderHelper : NSObject
//返回带帧数组的动画图像。
//[UIImage animationImageWithImages:duration:] 仅使用每个图像的持续时间的平均值。因此,如果不同的帧具有不同的持续时间,它将不能实现。
+ (UIImage * _Nullable)animatedImageWithFrames:(NSArray<SDWebImageFrame *> * _Nullable)frames;
//根据动画图像返回帧数组。
+ (NSArray<SDWebImageFrame *> * _Nullable)framesFromAnimatedImage:(UIImage * _Nullable)animatedImage;
#if SD_UIKIT || SD_WATCH
//将EXIF图像方向转换为iOS方向。
+ (UIImageOrientation)imageOrientationFromEXIFOrientation:(NSInteger)exifOrientation;
//将iOS方向转换为EXIF图像方向。
+ (NSInteger)exifOrientationFromImageOrientation:(UIImageOrientation)imageOrientation;
#endif
@end
SDWebImageFrame.h
@interface SDWebImageFrame : NSObject
//当前帧的图像 不能设置为动态图像
@property (nonatomic, strong, readonly, nonnull) UIImage *image;
//当前帧的持续时间。单位为秒,您不应将此设置为零。
@property (nonatomic, readonly, assign) NSTimeInterval duration;
//根据图像和持续时间生成帧
+ (instancetype _Nonnull)frameWithImage:(UIImage * _Nonnull)image duration:(NSTimeInterval)duration;
@end
例:
self.animateImageView = [[UIImageView alloc] init];
self.animateImageView.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:self.animateImageView];
[self.animateImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
SDWebImageFrame *frame1 = [SDWebImageFrame frameWithImage:[UIImage imageNamed:@"111.jpeg"] duration:0.3];
SDWebImageFrame *frame2 = [SDWebImageFrame frameWithImage:[UIImage imageNamed:@"222.jpeg"] duration:0.5];
SDWebImageFrame *frame3 = [SDWebImageFrame frameWithImage:[UIImage imageNamed:@"333.jpg"] duration:0.8];
self.animateImageView.image = [SDWebImageCoderHelper animatedImageWithFrames:@[frame1, frame2, frame3]];
效果如下
123.gif
SDWebImageCodersManager.h
@interface SDWebImageCodersManager : NSObject<SDWebImageCoder>
//单例
+ (nonnull instancetype)sharedInstance;
//编码器管理器中的所有编码器。
//编码器数组是一个优先级队列,这意味着后添加的编码器将具有最高优先级
//默认只有SDWebImageImageIOCoder
@property (nonatomic, copy, readwrite, nullable) NSArray<id<SDWebImageCoder>> *coders;
//添加一个新的编码器 新增的编码器优先级最高
- (void)addCoder:(nonnull id<SDWebImageCoder>)coder;
//移除一个编码器
- (void)removeCoder:(nonnull id<SDWebImageCoder>)coder;
@end
例:
self.animateImageView = [[UIImageView alloc] init];
[self.view addSubview:self.animateImageView];
[self.animateImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
NSLog(@"%@", [SDWebImageCodersManager sharedInstance].coders);
[self.animateImageView sd_setImageWithURL:[NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1591247443713&di=3fbe0d6527c3f6f2a99cdae6a980faf0&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20171228%2F1c446e1cd30e43c3a1fa08c83020617d.gif"]];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"切换"
style:UIBarButtonItemStyleDone target:self action:@selector(controlAction:)];
- (void)controlAction:(id)sender {
if ([sender isEqual:self.navigationItem.rightBarButtonItem]) {
//切换
//添加或移除SDWebImageGIFCoder编码器
if ([[SDWebImageCodersManager sharedInstance].coders containsObject:[SDWebImageGIFCoder sharedCoder]]) {
[[SDWebImageCodersManager sharedInstance] removeCoder:[SDWebImageGIFCoder sharedCoder]];
} else {
[[SDWebImageCodersManager sharedInstance] addCoder:[SDWebImageGIFCoder sharedCoder]];
}
//删除图像缓存
[SDWebImageManager.sharedManager.imageCache clearMemory];
[SDWebImageManager.sharedManager.imageCache clearDiskOnCompletion:nil];
//重新加载图像
self.animateImageView.image = nil;
[self.animateImageView sd_setImageWithURL:[NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1591247443713&di=3fbe0d6527c3f6f2a99cdae6a980faf0&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20171228%2F1c446e1cd30e43c3a1fa08c83020617d.gif"]];
}
}
效果如下 默认没有SDWebImageGIFCoder编码器 当点切换添加后 就可以加载动图了
123.gif
UIImage+MemoryCacheCost.h
@interface UIImage (MemoryCacheCost)
//所占内存的成本 等于image.size.height * image.size.width
//当为动图时 为所有图像成本之和
@property (assign, nonatomic) NSUInteger sd_memoryCost;
@end
SDImageCacheConfig.h
@interface SDImageCacheConfig : NSObject
//对下载和缓存的图像进行解压缩可以提高性能,但会占用大量内存。
//默认为YES。如果由于过多的内存消耗而导致崩溃,请将其设置为NO。
@property (assign, nonatomic) BOOL shouldDecompressImages;
//是否禁用iCloud备份
//默认为YES
@property (assign, nonatomic) BOOL shouldDisableiCloud;
//是否使用内存缓存
//默认为YES
//若禁用内存缓存,弱内存缓存也将被禁用。
@property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
//是否使用弱内存缓存 默认为YES
//启用后,缓存存储到内存的同时将将图像也存储在弱映射表中
//当触发内存警告时,存于内存中的图像会被删除,但可以从弱映射表中快速获取图像。
//例如,当应用进入后台并且内存被清除时,导致在重新进入前台时闪烁。
@property (assign, nonatomic) BOOL shouldUseWeakMemoryCache;
//从磁盘读取缓存时的读取选项 默认为0 可设置为NSDataReadingMappedIfSafe以提高性能。
@property (assign, nonatomic) NSDataReadingOptions diskCacheReadingOptions;
//将缓存写入磁盘时的写入选项
//默认为NSDataWritingAtomic 可设置为NSDataWritingWithoutOverwriting以防止覆盖现有文件。
@property (assign, nonatomic) NSDataWritingOptions diskCacheWritingOptions;
//将图像保留在缓存中的最长时间(以秒为单位)。 默认为一周
@property (assign, nonatomic) NSInteger maxCacheAge;
//缓存的最大大小,以byte为单位 默认为0 无限制
@property (assign, nonatomic) NSUInteger maxCacheSize;
//清除磁盘缓存时需要参照的属性 默认为SDImageCacheConfigExpireTypeModificationDate
@property (assign, nonatomic) SDImageCacheConfigExpireType diskCacheExpireType;
typedef NS_ENUM(NSUInteger, SDImageCacheConfigExpireType) {
//访问日期 每当访问图像后会更新该日期
SDImageCacheConfigExpireTypeAccessDate,
//修改日期 图像最后的修改日期
SDImageCacheConfigExpireTypeModificationDate
};
@end
SDImageCache.h
@interface SDImageCache : NSObject
#pragma mark - Properties
//缓存器的配置
@property (nonatomic, nonnull, readonly) SDImageCacheConfig *config;
//最大的内存成本
@property (assign, nonatomic) NSUInteger maxMemoryCost;
//最大可缓存在内存的个数
@property (assign, nonatomic) NSUInteger maxMemoryCountLimit;
#pragma mark - Singleton and initialization
//单例
//路径为 沙盒/Library/Caches/default/com.hackemist.SDWebImageCache.default
+ (nonnull instancetype)sharedImageCache;
//初始化一个自定义名字的缓存器
//路径为 沙盒/Library/Caches/ns
- (nonnull instancetype)initWithNamespace:(nonnull NSString *)ns;
//初始化一个自定义名字和路径的缓存器
//路径为 directory/com.hackemist.SDWebImageCache.ns
- (nonnull instancetype)initWithNamespace:(nonnull NSString *)ns
diskCacheDirectory:(nonnull NSString *)directory NS_DESIGNATED_INITIALIZER;
#pragma mark - Cache paths
//通过名字获取路径
//路径为 沙盒/Library/Caches/fullNamespace
- (nullable NSString *)makeDiskCachePath:(nonnull NSString*)fullNamespace;
//添加只读缓存路径
//SDWebCache只会在此路径搜索图像,不会对此文件夹增删改,需要用户手动增删改
- (void)addReadOnlyCachePath:(nonnull NSString *)path;
#pragma mark - Store Ops
//以给定的密钥将图像异步存储到内存和磁盘缓存中。
//imageData 数像数据
//不为空时则将imageData存入磁盘中 为空时则将image编码为data再存入磁盘中
//key 唯一的图片缓存键,通常是[[SDWebImageManager sharedManager] cacheKeyForURL:url]
//toDisk为YES时 则将图像存储到磁盘缓存
- (void)storeImage:(nullable UIImage *)image
imageData:(nullable NSData *)imageData
forKey:(nullable NSString *)key
toDisk:(BOOL)toDisk
completion:(nullable SDWebImageNoParamsBlock)completionBlock;
//completionBlock 操作完成的回调
typedef void(^SDWebImageNoParamsBlock)(void);
//imageData = nil
- (void)storeImage:(nullable UIImage *)image
forKey:(nullable NSString *)key
toDisk:(BOOL)toDisk
completion:(nullable SDWebImageNoParamsBlock)completionBlock;
//imageData = nil toDisk = YES
- (void)storeImage:(nullable UIImage *)image
forKey:(nullable NSString *)key
completion:(nullable SDWebImageNoParamsBlock)completionBlock;
//将imageData同步存储到给定的密钥的磁盘缓存中。
- (void)storeImageDataToDisk:(nullable NSData *)imageData forKey:(nullable NSString *)key;
#pragma mark - Query and Retrieve Ops
//异步检查磁盘缓存中是否已存在图像(不加载图像)
//key 唯一的图片缓存键
- (void)diskImageExistsWithKey:(nullable NSString *)key completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock;
//completionBlock 完成的回调
//isInCache 是否在缓存中
typedef void(^SDWebImageCheckCacheCompletionBlock)(BOOL isInCache);
//同步检查磁盘缓存中是否已存在图像数据(不加载图像)
- (BOOL)diskImageDataExistsWithKey:(nullable NSString *)key;
// 同步查询给定键的图像数据。
- (nullable NSData *)diskImageDataForKey:(nullable NSString *)key;
//异步查询缓存并在完成时调用完成的回调
//返回一个NSOperation 可调用[operation cancel]来取消 取消后不会回调
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key options:(SDImageCacheOptions)options done:(nullable SDCacheQueryCompletedBlock)doneBlock;
//缓存选项
typedef NS_OPTIONS(NSUInteger, SDImageCacheOptions) {
//默认情况下,当映像缓存在内存中时,我们不查询磁盘数据。
//此标志可以强制同时查询磁盘数据
SDImageCacheQueryDataWhenInMemory = 1 << 0,
//默认情况下,我们同步查询内存缓存,异步查询磁盘缓存。
//此掩码可以强制同步查询磁盘缓存。
SDImageCacheQueryDiskSync = 1 << 1,
//默认情况下,图像会根据其原始大小进行解码。
//在iOS上,此标志会将图像缩小到与设备的受限内存兼容的大小。
SDImageCacheScaleDownLargeImages = 1 << 2
};
//doneBlock 完成的回调
typedef void(^SDCacheQueryCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType);
//此时options = 0
- (nullable NSOperation *)queryCacheOperationForKey:(nullable NSString *)key done:(nullable SDCacheQueryCompletedBlock)doneBlock;
// 同步查询内存缓存。
- (nullable UIImage *)imageFromMemoryCacheForKey:(nullable NSString *)key;
//同步查询磁盘缓存
- (nullable UIImage *)imageFromDiskCacheForKey:(nullable NSString *)key;
//先同步查询内存缓存 若没有再同步查询磁盘缓存
- (nullable UIImage *)imageFromCacheForKey:(nullable NSString *)key;
#pragma mark - Remove Ops
//异步地从内存和磁盘缓存中删除映像 完成后返回空回调
- (void)removeImageForKey:(nullable NSString *)key withCompletion:(nullable SDWebImageNoParamsBlock)completion;
//从内存和可选的磁盘缓存异步删除映像
//fromDisk 为YES时 同时从磁盘删除
- (void)removeImageForKey:(nullable NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(nullable SDWebImageNoParamsBlock)completion;
#pragma mark - Cache clean Ops
//删除所有的内存缓存
- (void)clearMemory;
//异步清除所有磁盘缓存的图像。非阻塞方法-立即返回一个空回调
- (void)clearDiskOnCompletion:(nullable SDWebImageNoParamsBlock)completion;
//异步从磁盘中删除所有过期的缓存图像。非阻塞方法-立即返回一个空回调
- (void)deleteOldFilesWithCompletionBlock:(nullable SDWebImageNoParamsBlock)completionBlock;
#pragma mark - Cache Info
//获取磁盘缓存使用的大小
- (NSUInteger)getSize;
//获取磁盘缓存中的图像数量
- (NSUInteger)getDiskCount;
//异步计算磁盘缓存的大小。
- (void)calculateSizeWithCompletionBlock:(nullable SDWebImageCalculateSizeBlock)completionBlock;
//completionBlock 完成后回调
//fileCount 文件数量 totalSize 总大小
typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger totalSize);
#pragma mark - Cache Paths
//获取特定键的缓存路径(需要缓存路径根文件夹)
//key 密钥(可以使用cacheKeyForURL从url获得)
//path 缓存路径根文件夹
//详情可见sharedImageCache: initWithNamespace: initWithNamespace:diskCacheDirectory:这三方法
- (nullable NSString *)cachePathForKey:(nullable NSString *)key inPath:(nonnull NSString *)path;
//获取特定键的默认缓存路径
//key 密钥(可以使用cacheKeyForURL从url获得)
- (nullable NSString *)defaultCachePathForKey:(nullable NSString *)key;
@end
例:
self.baseImageView = [[UIImageView alloc] init];
self.baseImageView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:self.baseImageView];
[self.baseImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
__weak typeof(self) weakSelf = self;
[UIActivityIndicatorView appearance].color = [UIColor redColor];
[self.baseImageView sd_setShowActivityIndicatorView:YES];
[self.baseImageView sd_internalSetImageWithURL:[NSURL URLWithString:@"https://nokiatech.github.io/heif/content/images/ski_jump_1440x960.heic"] placeholderImage:nil options:SDWebImageRetryFailed operationKey:nil setImageBlock:^(UIImage * _Nullable image, NSData * _Nullable imageData) {
//需要手动在该回调中设置image
weakSelf.baseImageView.image = image;
} progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
NSLog(@"%.2f%%", receivedSize*100.0/expectedSize);
} completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
if (image) {
NSLog(@"completed");
}
} context:nil];
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"同步" style:UIBarButtonItemStyleDone target:self action:@selector(controlAction:)];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"异步" style:UIBarButtonItemStyleDone target:self action:@selector(controlAction:)];
self.navigationItem.rightBarButtonItems = @[item1, item2];
- (void)controlAction:(UIBarButtonItem *)sender {
__weak typeof(self) weakSelf = self;
if ([sender.title isEqualToString:@"同步"]) {
NSString *urlString = [[SDWebImageManager sharedManager] cacheKeyForURL:self.baseImageView.sd_imageURL];
[self.baseImageView sd_addActivityIndicator];
self.baseImageView.image = nil;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
weakSelf.baseImageView.image = [[SDImageCache sharedImageCache] imageFromCacheForKey:urlString];
[weakSelf.baseImageView sd_removeActivityIndicator];
});
} else if ([sender.title isEqualToString:@"异步"]) {
NSString *urlString = [[SDWebImageManager sharedManager] cacheKeyForURL:self.baseImageView.sd_imageURL];
[self.baseImageView sd_addActivityIndicator];
self.baseImageView.image = nil;
NSOperation *operation = [[SDImageCache sharedImageCache] queryCacheOperationForKey:urlString done:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
weakSelf.baseImageView.image = image;
[weakSelf.baseImageView sd_removeActivityIndicator];
});
}];
//可调用cancel来取消读取
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[operation cancel];
[weakSelf.baseImageView sd_removeActivityIndicator];
});
}
}
效果如下
123.gif
SDWebImageDownloader.h
//与下载相关的令牌。可用于取消下载
@interface SDWebImageDownloadToken : NSObject <SDWebImageOperation>
//下载的URL。只读,不应修改
@property (nonatomic, strong, nullable) NSURL *url;
//等于SDWebImageDownloaderOperation的addHandlersForProgress:completed
//只读,不应修改和操作
//若要取消下载 使用SDWebImageDownloadToken的cancel
@property (nonatomic, strong, nullable) id downloadOperationCancelToken;
@end
//对图像加载进行了优化的异步下载器
@interface SDWebImageDownloader : NSObject
//单例
//sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]
+ (nonnull instancetype)sharedDownloader;
//使用指定的会话配置创建实例。
//配置中的timeoutIntervalForRequest将被downloadTimeout覆盖
- (nonnull instancetype)initWithSessionConfiguration:(nullable NSURLSessionConfiguration *)sessionConfiguration NS_DESIGNATED_INITIALIZER;
// 对下载并缓存的图像进行解压缩可以提高性能,但会占用大量内存。
//默认为YES。如果由于过多的内存消耗而导致崩溃,请将其设置为NO。
@property (assign, nonatomic) BOOL shouldDecompressImages;
//并发下载的最大数量 默认为6
@property (assign, nonatomic) NSInteger maxConcurrentDownloads;
//当前仍需要下载的数量 只读
@property (readonly, nonatomic) NSUInteger currentDownloadCount;
//下载操作的超时值(以秒为单位)。默认值15.0。
@property (assign, nonatomic) NSTimeInterval downloadTimeout;
//内部NSURLSession使用的配置。
//只读 直接更改此对象无效。
//使用SDWebImageDownloader的createNewSessionWithConfiguration修改
@property (readonly, nonatomic, nonnull) NSURLSessionConfiguration *sessionConfiguration;
//下载操作执行顺序。默认值为SDWebImageDownloaderFIFOExecutionOrder
@property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder;
typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
//所有下载操作将以队列方式(先进先出)执行
SDWebImageDownloaderFIFOExecutionOrder,
//所有下载操作将以堆栈样式(后进先出)执行。
SDWebImageDownloaderLIFOExecutionOrder
};
//设置为请求操作的URL凭据。
@property (strong, nonatomic, nullable) NSURLCredential *urlCredential;
//设置为请求操作的URL凭据的用户名。
@property (strong, nonatomic, nullable) NSString *username;
//设置为请求操作的URL凭据的密码。
@property (strong, nonatomic, nullable) NSString *password;
//设置过滤器以选择用于下载图像HTTP请求的标头。
@property (nonatomic, copy, nullable) SDWebImageDownloaderHeadersFilterBlock headersFilter;
//url 图像的url
//headers NSMutableDictionary<NSString *, NSString *>
typedef SDHTTPHeadersDictionary * _Nullable (^SDWebImageDownloaderHeadersFilterBlock)(NSURL * _Nullable url, SDHTTPHeadersDictionary * _Nullable headers);
//为每个下载HTTP请求的HTTP标头设置一个值。
//value 标头字段的值。使用nil值删除标头。
//field 要设置的标头字段的名称。
- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(nullable NSString *)field;
//返回指定的HTTP标头字段的值。
- (nullable NSString *)valueForHTTPHeaderField:(nullable NSString *)field;
// 设置下载操作的类名
//operationClass NSOperation的子类并实现SDWebImageDownloaderOperationInterface协议
//默认为SDWebImageDownloaderOperation,传递nil将还原为SDWebImageDownloaderOperation
- (void)setOperationClass:(nullable Class)operationClass;
//使用给定的URL创建SDWebImageDownloader异步下载器实例
//返回SDWebImageDownloadToken 可调用cancle取消下载
//options 下载类型选项
//progressBlock 进度回调
//completedBlock 完成回调
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
options:(SDWebImageDownloaderOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock;
//使用给定的URL创建SDWebImageDownloader异步下载器实例
//返回SDWebImageDownloadToken 可调用cancle取消下载
//options = 0 progressBlock = nil
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock;
typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
//将下载置于低队列优先级和低任务优先级
SDWebImageDownloaderLowPriority = 1 << 0,
//该标志启用渐进式下载,在下载过程中图像会像浏览器一样逐步显示。
SDWebImageDownloaderProgressiveDownload = 1 << 1,
//默认情况下,请求阻止使用NSURLCache。
//带有此标志,NSURLCache与默认策略一起使用。
SDWebImageDownloaderUseNSURLCache = 1 << 2,
//如果从NSURLCache读取了图像,则completedBlock的image/imageData将返回nil
//需与SDWebImageDownloaderUseNSURLCache结合使用。
SDWebImageDownloaderIgnoreCachedResponse = 1 << 3,
//应用程序进入后台运行,会继续下载图像,这是通过在后台请求系统额外的时间来完成请求来实现的。
//如果后台任务到期,则该操作将被取消。
SDWebImageDownloaderContinueInBackground = 1 << 4,
//通过设置NSMutableURLRequest.HTTPShouldHandleCookies = YES处理存储在NSHTTPCookieStore中的cookie。
SDWebImageDownloaderHandleCookies = 1 << 5,
//启用以允许不受信任的SSL证书。
//用于测试目的。在生产中请谨慎使用。
SDWebImageDownloaderAllowInvalidSSLCertificates = 1 << 6,
//将下载置于高队列优先级和高任务优先级。
SDWebImageDownloaderHighPriority = 1 << 7,
//会缩小图像
SDWebImageDownloaderScaleDownLargeImages = 1 << 8,
};
//取消先前使用-downloadImageWithURL:options:progress:completed排队的下载
//等效于[token cancal]
- (void)cancel:(nullable SDWebImageDownloadToken *)token;
//设置下载队列暂停状态
- (void)setSuspended:(BOOL)suspended;
//取消队列中的所有下载操作
- (void)cancelAllDownloads;
//强制SDWebImageDownloader创建并使用通过sessionConfiguration初始化的新NSURLSession。
//队列中所有现有的下载操作将被取消。
//timeoutIntervalForRequest将被downloadTimeout覆盖。
- (void)createNewSessionWithConfiguration:(nonnull NSURLSessionConfiguration *)sessionConfiguration;
//使托管会话无效,可以选择取消挂起的操作。
//cancelPendingOperations是否取消挂起的操作。
//如果使用自定义下载器而不是共享下载器,则在不使用它时需要调用此方法,以避免内存泄漏
//在共享下载器上调用此方法无效。(sharedDownloader创建的)
- (void)invalidateSessionAndCancel:(BOOL)cancelPendingOperations;
@end
例:
self.baseImageView = [[UIImageView alloc] init];
self.baseImageView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:self.baseImageView];
[self.baseImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
__weak typeof(self) weakSelf = self;
[UIActivityIndicatorView appearance].color = [UIColor redColor];
[self.baseImageView sd_addActivityIndicator];
NSString *userName = @"userName";
NSString *password = @"password";
//添加凭证 这两种写法效果相同
[SDWebImageDownloader sharedDownloader].urlCredential = [NSURLCredential credentialWithUser:userName
password:password persistence:NSURLCredentialPersistenceForSession];
// [SDWebImageDownloader sharedDownloader].username = userName;
// [SDWebImageDownloader sharedDownloader].password = password;
//添加头部参数 这两种写法效果相同
[SDWebImageDownloader sharedDownloader].headersFilter = ^SDHTTPHeadersDictionary * _Nullable
(NSURL * _Nullable url, SDHTTPHeadersDictionary * _Nullable headers) {
SDHTTPHeadersDictionary *dict = [headers mutableCopy];
//新增
[dict setValue:@"value" forKey:@"key"];
// //删除
// [headers setValue:nil forKey:@"key"];
return dict;
};
// [[SDWebImageDownloader sharedDownloader] setValue:@"value" forHTTPHeaderField:@"key"];
// [[SDWebImageDownloader sharedDownloader] setValue:nil forHTTPHeaderField:@"key"];
//设置自定义下载器
[[SDWebImageDownloader sharedDownloader] setOperationClass:[SDWebImageDownloaderOperation class]];
SDWebImageDownloadToken *token = [[SDWebImageDownloader sharedDownloader]
downloadImageWithURL:[NSURL URLWithString:@"https://nokiatech.github.io/heif/content/images/ski_jump_1440x960.heic"]
options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
NSLog(@"%.2f%%", receivedSize*100.0/expectedSize);
} completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
if (finished) {
weakSelf.baseImageView.image = image;
NSLog(@"finished");
[weakSelf.baseImageView sd_removeActivityIndicator];
}
}];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[weakSelf.baseImageView sd_removeActivityIndicator];
//取消下载任务 这两种效果相同
[token cancel];
// [[SDWebImageDownloader sharedDownloader] cancel:token];
//取消所有下载任务
// [[SDWebImageDownloader sharedDownloader] cancelAllDownloads];
});
SDWebImageDownloaderOperation.h
//下载器委托 若要自定义下载器 需要为NSOperation的子类并且实现该委托
@protocol SDWebImageDownloaderOperationInterface <NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
@required
- (nonnull instancetype)initWithRequest:(nullable NSURLRequest *)request
inSession:(nullable NSURLSession *)session
options:(SDWebImageDownloaderOptions)options;
- (nullable id)addHandlersForProgress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock;
- (BOOL)shouldDecompressImages;
- (void)setShouldDecompressImages:(BOOL)value;
- (nullable NSURLCredential *)credential;
- (void)setCredential:(nullable NSURLCredential *)value;
- (BOOL)cancel:(nullable id)token;
@optional
- (nullable NSURLSessionTask *)dataTask;
@end
@interface SDWebImageDownloaderOperation : NSOperation <SDWebImageDownloaderOperationInterface, SDWebImageOperation>
//操作任务使用的请求 只读
@property (strong, nonatomic, readonly, nullable) NSURLRequest *request;
//会话任务 只读
@property (strong, nonatomic, readonly, nullable) NSURLSessionTask *dataTask;
//对下载和缓存的图像进行解压缩可以提高性能,但会占用大量内存。
//默认为YES。如果由于过多的内存消耗而导致崩溃,请将其设置为NO。
@property (assign, nonatomic) BOOL shouldDecompressImages;
//已废弃
@property (nonatomic, assign) BOOL shouldUseCredentialStorage __deprecated_msg("Property deprecated. Does nothing. Kept only for backwards compatibility");
//用于-URLSession:task:didReceiveChallenge:completionHandler:委托方法中的凭据。
@property (nonatomic, strong, nullable) NSURLCredential *credential;
//下载类型选项 只读
@property (assign, nonatomic, readonly) SDWebImageDownloaderOptions options;
//预计大小
@property (assign, nonatomic) NSInteger expectedSize;
//操作任务返回的响应。
@property (strong, nonatomic, nullable) NSURLResponse *response;
//初始化
- (nonnull instancetype)initWithRequest:(nullable NSURLRequest *)request
inSession:(nullable NSURLSession *)session
options:(SDWebImageDownloaderOptions)options NS_DESIGNATED_INITIALIZER;
//将进度回调和完成回调变成字典保存在数组里
//返回该字典
- (nullable id)addHandlersForProgress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock;
//取消一组回调。一旦取消所有回调,NSOperation将被取消。
//token 令牌 为上面方法返回的字典
//若已取消全部回调 都返回YES
- (BOOL)cancel:(nullable id)token;
@end
SDWebImageManager.h
@interface SDWebImageManager : NSObject
//委托
@property (weak, nonatomic, nullable) id <SDWebImageManagerDelegate> delegate;
//图像缓存器
@property (strong, nonatomic, readonly, nullable) SDImageCache *imageCache;
//图像下载器
@property (strong, nonatomic, readonly, nullable) SDWebImageDownloader *imageDownloader;
//缓存键过滤器
//SDWebImageManager.-cacheKeyForURL 会使用该回调
@property (nonatomic, copy, nullable) SDWebImageCacheKeyFilterBlock cacheKeyFilter;
//cacheKeyFilter 默认返回url.absoluteString;
typedef NSString * _Nullable(^SDWebImageCacheKeyFilterBlock)(NSURL * _Nullable url);
//高速缓存序列化器,用于将解码的图像(源下载的数据)转换为用于存储到磁盘高速缓存的实际数据。
//从全局队列中调用此方法,以便不阻塞主线程。
//默认值为nil。意味着我们只将源下载的数据存储到磁盘缓存中。
@property (nonatomic, copy, nullable) SDWebImageCacheSerializerBlock cacheSerializer;
//cacheSerializer 如果返回nil,则表示从将image编码成数据
typedef NSData * _Nullable(^SDWebImageCacheSerializerBlock)(UIImage * _Nonnull image, NSData * _Nullable data, NSURL * _Nullable imageURL);
//单例
//cache = [SDImageCache sharedImageCache]
//downloader = [SDWebImageDownloader sharedDownloader]
+ (nonnull instancetype)sharedManager;
//通过自定义缓存器和下载器初始化
- (nonnull instancetype)initWithCache:(nonnull SDImageCache *)cache downloader:(nonnull SDWebImageDownloader *)downloader NS_DESIGNATED_INITIALIZER;
//加载图像 如果不存在于缓存中,则以指定的URL下载图像
//completedBlock 完成后回调 不能为空
//当使用SDWebImageProgressiveDownload时,重复调用该块,但finished为NO
//完全下载图像后,inished为YES
- (nullable id <SDWebImageOperation>)loadImageWithURL:(nullable NSURL *)url
options:(SDWebImageOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDInternalCompletionBlock)completedBlock;
//将图像保存到指定的URL的缓存中
- (void)saveImageToCache:(nullable UIImage *)image forURL:(nullable NSURL *)url;
//取消所有当前的操作
- (void)cancelAll;
//返回是否有正在运行的操作
- (BOOL)isRunning;
//异步检查图像是否已经被缓存
//注意:completionBlock始终在主队列上执行
- (void)cachedImageExistsForURL:(nullable NSURL *)url
completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock;
//异步检查图像是否仅缓存在磁盘上
//注意:completionBlock始终在主队列上执行
- (void)diskImageExistsForURL:(nullable NSURL *)url
completion:(nullable SDWebImageCheckCacheCompletionBlock)completionBlock;
//返回指定url的key
//默认为url.absoluteString 若实现的cacheKeyFilter,会返回过滤后的字符串
- (nullable NSString *)cacheKeyForURL:(nullable NSURL *)url;
@end
@protocol SDWebImageManagerDelegate <NSObject>
@optional
//在缓存中找不到图像时要下载的图像。
//返回NO时,在缓存中未找到时不会下载图像。
//如果未实现,则表示YES。
- (BOOL)imageManager:(nonnull SDWebImageManager *)imageManager shouldDownloadImageForURL:(nullable NSURL *)imageURL;
//发生下载错误时将其标记为失败的URL。
//返回YES以将该URL标记为失败。
- (BOOL)imageManager:(nonnull SDWebImageManager *)imageManager shouldBlockFailedURL:(nonnull NSURL *)imageURL withError:(nonnull NSError *)error;
//允许在下载图像后立即将其转换并将其缓存在磁盘和内存上。
//注意:从全局队列中调用此方法是为了不阻塞主线程。
- (nullable UIImage *)imageManager:(nonnull SDWebImageManager *)imageManager transformDownloadedImage:(nullable UIImage *)image withURL:(nullable NSURL *)imageURL;
@end
例:
self.baseImageView = [[UIImageView alloc] init];
self.baseImageView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:self.baseImageView];
[self.baseImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
self.baseImageView1 = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"111.jpeg"]];
self.baseImageView1.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:self.baseImageView1];
[self.baseImageView1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.baseImageView.mas_bottom).offset(50);
make.left.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
NSData *imageData = self.baseImageView1.image.sd_imageData;
__weak typeof(self) weakSelf = self;
[UIActivityIndicatorView appearance].color = [UIColor redColor];
[self.baseImageView sd_addActivityIndicator];
NSURL *imageUrl = [NSURL URLWithString:@"https://b-ssl.duitang.com/uploads/item/201507/04/20150704212949_PSfNZ.jpeg"];
[[SDWebImageManager sharedManager] loadImageWithURL:imageUrl options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
NSLog(@"%.2f%%", receivedSize*100.0/expectedSize);
} completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
if (finished) {
NSLog(@"finished");
weakSelf.baseImageView.image = image;
[weakSelf.baseImageView sd_removeActivityIndicator];
}
}];
SDWebImageManager.sharedManager.cacheKeyFilter = ^NSString * _Nullable(NSURL * _Nullable url) {
//将imageUrl的缓存键改为demo12345 则可通过该缓存键获取图像 而不是默认的url.absoluteString
if ([url isEqual:imageUrl]) {
return @"demo12345";
}
return url.absoluteString;
};
SDWebImageManager.sharedManager.cacheSerializer = ^NSData * _Nullable(UIImage * _Nonnull image, NSData * _Nullable data, NSURL * _Nullable imageURL) {
//将imageUrl需要存入硬盘的数据替换成imageData 但此时内存中存的数据仍是data
if ([imageURL isEqual:imageUrl]) {
return imageData;
}
return data;
};
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"内存" style:UIBarButtonItemStyleDone target:self action:@selector(controlAction:)];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"硬盘" style:UIBarButtonItemStyleDone target:self action:@selector(controlAction:)];
self.navigationItem.rightBarButtonItems = @[item1, item2];
- (void)controlAction:(UIBarButtonItem *)sender {
if ([sender.title isEqualToString:@"内存"]) {
UIImage *image = [[SDWebImageManager sharedManager].imageCache imageFromMemoryCacheForKey:@"demo12345"];
self.baseImageView1.image = image;
} else if ([sender.title isEqualToString:@"硬盘"]) {
//从硬盘中读取数据后 会将该数据存入内存中 之前内存的数据就会被覆盖
UIImage *image = [[SDWebImageManager sharedManager].imageCache imageFromDiskCacheForKey:@"demo12345"];
self.baseImageView1.image = image;
}
}
效果如下 点击内存时 下图使用data的图像
点击硬盘时 使用硬盘保存的imageData 此时内存中也会被imageData覆盖
再点击内存 会显示内存的保存的imageData
123.gif
SDWebImagePrefetcher.h
//图像预载器
@interface SDWebImagePrefetcher : NSObject
//单例
//manager = [SDWebImageManager new]
+ (nonnull instancetype)sharedImagePrefetcher;
//通过自定义管理器初始化
- (nonnull instancetype)initWithImageManager:(nonnull SDWebImageManager *)manager NS_DESIGNATED_INITIALIZER;
//图像管理器 只读
@property (strong, nonatomic, readonly, nonnull) SDWebImageManager *manager;
//可以同时预载的最大URL数。默认为3。
@property (nonatomic, assign) NSUInteger maxConcurrentDownloads;
//图像下载选项 默认为SDWebImageLowPriority。
@property (nonatomic, assign) SDWebImageOptions options;
//预载的队列 默认为主队列。
@property (strong, nonatomic, nonnull) dispatch_queue_t prefetcherQueue;
//委托
@property (weak, nonatomic, nullable) id <SDWebImagePrefetcherDelegate> delegate;
//排队预载,当前一次下载一个图像,并跳过下载失败的图像并继续下载下一个图像。
//会取消所有先前运行的预载操作。
- (void)prefetchURLs:(nullable NSArray<NSURL *> *)urls;
- (void)prefetchURLs:(nullable NSArray<NSURL *> *)urls
progress:(nullable SDWebImagePrefetcherProgressBlock)progressBlock
completed:(nullable SDWebImagePrefetcherCompletionBlock)completionBlock;
//progressBlock 进度回调
//noOfFinishedUrls 已完成的数量 noOfTotalUrls 总数量
typedef void(^SDWebImagePrefetcherProgressBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls);
//completionBlock 完成回调 noOfFinishedUrls 已完成的数量 noOfSkippedUrls 下载失败的数量
typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls);
//取消所有的预载操作
- (void)cancelPrefetching;
@end
@protocol SDWebImagePrefetcherDelegate <NSObject>
@optional
//每预载完成一张图像时调用
- (void)imagePrefetcher:(nonnull SDWebImagePrefetcher *)imagePrefetcher didPrefetchURL:(nullable NSURL *)imageURL finishedCount:(NSUInteger)finishedCount totalCount:(NSUInteger)totalCount;
////全部预载完成时调用
- (void)imagePrefetcher:(nonnull SDWebImagePrefetcher *)imagePrefetcher didFinishWithTotalCount:(NSUInteger)totalCount skippedCount:(NSUInteger)skippedCount;
@end
例:
self.baseImageView = [[UIImageView alloc] init];
self.baseImageView.backgroundColor = [UIColor lightGrayColor];
[self.view addSubview:self.baseImageView];
[self.baseImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self.view);
make.height.mas_equalTo(200);
}];
__weak typeof(self) weakSelf = self;
[UIActivityIndicatorView appearance].color = [UIColor redColor];
[self.baseImageView sd_addActivityIndicator];
NSArray *urls = @[[NSURL URLWithString:@"https://iknow-pic.cdn.bcebos.com/c83d70cf3bc79f3d6e7bf85db8a1cd11738b29c0"],
[NSURL URLWithString:@"https://b-ssl.duitang.com/uploads/item/201507/04/20150704212949_PSfNZ.jpeg"],
[NSURL URLWithString:@"https://wx3.sinaimg.cn/orj360/6987953cly1g9kbs5d56ij20k024sh2w.jpg"]];
[[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:urls progress:^(NSUInteger noOfFinishedUrls, NSUInteger noOfTotalUrls) {
NSLog(@"%ld/%ld", noOfFinishedUrls, noOfTotalUrls);
} completed:^(NSUInteger noOfFinishedUrls, NSUInteger noOfSkippedUrls) {
[weakSelf.baseImageView sd_removeActivityIndicator];
weakSelf.index = 0;
weakSelf.baseImageView.image = [[SDImageCache sharedImageCache] imageFromCacheForKey:[[SDWebImageManager sharedManager] cacheKeyForURL:urls[weakSelf.index]]];
}];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"切换" style:UIBarButtonItemStyleDone target:self action:@selector(controlAction:)];
- (void)controlAction:(UIBarButtonItem *)sender {
if ([sender isEqual:self.navigationItem.rightBarButtonItem]) {
NSArray *urls = @[[NSURL URLWithString:@"https://iknow-pic.cdn.bcebos.com/c83d70cf3bc79f3d6e7bf85db8a1cd11738b29c0"],
[NSURL URLWithString:@"https://b-ssl.duitang.com/uploads/item/201507/04/20150704212949_PSfNZ.jpeg"],
[NSURL URLWithString:@"https://wx3.sinaimg.cn/orj360/6987953cly1g9kbs5d56ij20k024sh2w.jpg"]];
self.index = (self.index+1)%urls.count;
self.baseImageView.image = [[SDImageCache sharedImageCache] imageFromCacheForKey:[[SDWebImageManager sharedManager] cacheKeyForURL:urls[self.index]]];
}
}
效果如下 预载后可直接从缓存中获取图像
输出
2020-06-22 16:57:09.472460+0800 SDWebImageDemo[3482:236673] 1/3
2020-06-22 16:57:09.519286+0800 SDWebImageDemo[3482:236673] 2/3
2020-06-22 16:57:09.646935+0800 SDWebImageDemo[3482:236673] 3/3
123.gif
UIImage+ForceDecode.h
@interface UIImage (ForceDecode)
//解压缩图像
+ (nullable UIImage *)decodedImageWithImage:(nullable UIImage *)image;
//解压缩图像并缩放
+ (nullable UIImage *)decodedAndScaledDownImageWithImage:(nullable UIImage *)image;
@end














网友评论