【iOS】 使用SDWebImage 定制你的缓存图片

SDWebImage是一个强大的网络图像异步缓存框架,使用非常方便。本章我们介绍如何对SDWebImage下载的网络图像进行定制处理。

一、接口API

SDWebImage 提供了对UIImageViewUIButton异步加载网络图片的UI扩展,你可以在文件UIImageView+WebCacheUIButton+WebCache 中查看具体实现。

我们看下UIImageView扩展的相关实现:

/**
 * Integrates SDWebImage async downloading and caching of remote images with UIImageView.
 */
@interface UIImageView (WebCache)

/**
 * Set the imageView `image` with an `url`.
 * The download is asynchronous and cached.
 * @param url The url for the image.
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url NS_REFINED_FOR_SWIFT;

/**
 * Set the imageView `image` with an `url` and a placeholder.
 * The download is asynchronous and cached.
 * @param url         The url for the image.
 * @param placeholder The image to be set initially, until the image request finishes.
 * @see sd_setImageWithURL:placeholderImage:options:
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
          placeholderImage:(nullable UIImage *)placeholder NS_REFINED_FOR_SWIFT;

/**
 * Set the imageView `image` with an `url`, placeholder and custom options.
 * The download is asynchronous and cached.
 * @param url         The url for the image.
 * @param placeholder The image to be set initially, until the image request finishes.
 * @param options     The options to use when downloading the image. @see SDWebImageOptions for the possible values.
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
          placeholderImage:(nullable UIImage *)placeholder
                   options:(SDWebImageOptions)options NS_REFINED_FOR_SWIFT;

/**
 * Set the imageView `image` with an `url`, placeholder, custom options and context.
 * The download is asynchronous and cached.
 * @param url         The url for the image.
 * @param placeholder The image to be set initially, until the image request finishes.
 * @param options     The options to use when downloading the image. @see SDWebImageOptions for the possible values.
 * @param context     A context contains different options to perform specify changes or processes, see `SDWebImageContextOption`. This hold the extra objects which `options` enum can not hold.
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
          placeholderImage:(nullable UIImage *)placeholder
                   options:(SDWebImageOptions)options
                   context:(nullable SDWebImageContext *)context;

/**
 * Set the imageView `image` with an `url`.
 * The download is asynchronous and cached.
 * @param url            The url for the image.
 * @param completedBlock A block called when operation has been completed. This block has no return value
 *                       and takes the requested UIImage as first parameter. In case of error the image parameter
 *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
 *                       indicating if the image was retrieved from the local cache or from the network.
 *                       The fourth parameter is the original image url.
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
                 completed:(nullable SDExternalCompletionBlock)completedBlock;

/**
 * Set the imageView `image` with an `url`, placeholder.
 * The download is asynchronous and cached.
 * @param url            The url for the image.
 * @param placeholder    The image to be set initially, until the image request finishes.
 * @param completedBlock A block called when operation has been completed. This block has no return value
 *                       and takes the requested UIImage as first parameter. In case of error the image parameter
 *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
 *                       indicating if the image was retrieved from the local cache or from the network.
 *                       The fourth parameter is the original image url.
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
          placeholderImage:(nullable UIImage *)placeholder
                 completed:(nullable SDExternalCompletionBlock)completedBlock NS_REFINED_FOR_SWIFT;

/**
 * Set the imageView `image` with an `url`, placeholder and custom options.
 * The download is asynchronous and cached.
 * @param url            The url for the image.
 * @param placeholder    The image to be set initially, until the image request finishes.
 * @param options        The options to use when downloading the image. @see SDWebImageOptions for the possible values.
 * @param completedBlock A block called when operation has been completed. This block has no return value
 *                       and takes the requested UIImage as first parameter. In case of error the image parameter
 *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
 *                       indicating if the image was retrieved from the local cache or from the network.
 *                       The fourth parameter is the original image url.
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
          placeholderImage:(nullable UIImage *)placeholder
                   options:(SDWebImageOptions)options
                 completed:(nullable SDExternalCompletionBlock)completedBlock;

/**
 * Set the imageView `image` with an `url`, placeholder and custom options.
 * The download is asynchronous and cached.
 * @param url            The url for the image.
 * @param placeholder    The image to be set initially, until the image request finishes.
 * @param options        The options to use when downloading the image. @see SDWebImageOptions for the possible values.
 * @param progressBlock  A block called while image is downloading
 *                       @note the progress block is executed on a background queue
 * @param completedBlock A block called when operation has been completed. This block has no return value
 *                       and takes the requested UIImage as first parameter. In case of error the image parameter
 *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
 *                       indicating if the image was retrieved from the local cache or from the network.
 *                       The fourth parameter is the original image url.
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
          placeholderImage:(nullable UIImage *)placeholder
                   options:(SDWebImageOptions)options
                  progress:(nullable SDImageLoaderProgressBlock)progressBlock
                 completed:(nullable SDExternalCompletionBlock)completedBlock;

/**
 * Set the imageView `image` with an `url`, placeholder, custom options and context.
 * The download is asynchronous and cached.
 * @param url            The url for the image.
 * @param placeholder    The image to be set initially, until the image request finishes.
 * @param options        The options to use when downloading the image. @see SDWebImageOptions for the possible values.
 * @param context        A context contains different options to perform specify changes or processes, see `SDWebImageContextOption`. This hold the extra objects which `options` enum can not hold.
 * @param progressBlock  A block called while image is downloading
 *                       @note the progress block is executed on a background queue
 * @param completedBlock A block called when operation has been completed. This block has no return value
 *                       and takes the requested UIImage as first parameter. In case of error the image parameter
 *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
 *                       indicating if the image was retrieved from the local cache or from the network.
 *                       The fourth parameter is the original image url.
 */
- (void)sd_setImageWithURL:(nullable NSURL *)url
          placeholderImage:(nullable UIImage *)placeholder
                   options:(SDWebImageOptions)options
                   context:(nullable SDWebImageContext *)context
                  progress:(nullable SDImageLoaderProgressBlock)progressBlock
                 completed:(nullable SDExternalCompletionBlock)completedBlock;

二、基础用法

如果你有使用SDWebImage框架经验,可以直接忽略此部分

本文我们只针对UIImageView , 使用前请导入#import<SDWebImage/UIImageView+WebCache.h>

1.1 异步加载网络图片

通常情况下你可以直接使用获取的图片URL地址加载网络图片,你可以在滚动的列表或者其他需要加载图片的地方调用以下接口

[self.imageView sd_setImageWithURL:[NSURL urlWithString:urlString]];

1.2 设置一个占位图

占位图会优先显示到UIImageView上,当图片加载成功后会替换占位图,占位图的显示时长与第一此加载网络图片进度有关,如果网络图片加载较慢,你可以很明显看到占位图,快则占位图一闪而过,当图片被缓存后,你几乎看不到占位图显示。

[self.imageView sd_setImageWithURL:[NSURL urlWithString:urlString] 
                  placeholderImage:[UIImage imageNamed:@"myPlaceHolder"]];

1.3 添加代理回调

如果你想要在图片加载成功后对做一些额外的处理,你需要配置一下代理回调block:

[self.imageView sd_setImageWithURL:[NSURL urlWithString:urlString] 
                  placeholderImage:[UIImage imageNamed:@"myPlaceHolder"]
                  completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
                      if (error) {
                      }
                      else {
                          
                      }
                  }];

1.4 使用Options

SDWebImage 提供了 SDWebImageOptions 缓存选项,你可以根据需要进行动态配置:

1.4.1 失败后重试
[self.imageView sd_setImageWithURL:[NSURL urlWithString:urlString] 
                  placeholderImage:[UIImage imageNamed:@"myPlaceHolder"]
                  options:SDWebImageRetryFailed
                  completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
                      if (error) {
                      }
                      else {
                          
                      }
                  }];
1.4.2 忽略磁盘缓存

你可以选择从内存中加载缓存,如果内存缓存不存在,则直接从网络下载,内存缓存读取数据非常快,但是当缓存达到阈值,图片缓存可能被丢弃,所以通常默认是先从内存查询,再从磁盘查询,然后从网络下载,虽然内存缓存是易失性缓存,但好在速度快,弥补了磁盘缓存IO开销大,读取速度慢的缺点,所以两者结合可以很好地实现图片缓存,建议你在自定义图片缓存框架的时候实现两者结合,而不是单独使用其中一种,另外通过改进内存缓存算法,也可以优化你的APP性能。

[self.imageView sd_setImageWithURL:[NSURL urlWithString:urlString] 
                  placeholderImage:[UIImage imageNamed:@"myPlaceHolder"]
                  options:SDWebImageRetryFailed | SDWebImageFromCacheOnly
                  completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
                      if (error) {
                      }
                      else {
                          
                      }
                  }];

还有其他选择你可以根据需要进行选择,具体不在一一描述

1.5 添加一个下载进度

SDWebImage 提供了 progressblock回调,你可以配置此 block获取当前图片下载进度

[self.imageView sd_setImageWithURL:[NSURL urlWithString:urlString] 
                  placeholderImage:[UIImage imageNamed:@"myPlaceHolder"]
                  options:SDWebImageRetryFailed | SDWebImageFromCacheOnly
                  progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * targetURL){
                      
                  }
                  completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
                      if (error) {
                      }
                      else {
                          
                      }
                  }];

二、高级扩展

在上面介绍的SDWebImageOptions 有一个选项做了以下描述:

/**
     * We usually don't apply transform on animated images as most transformers could not manage animated images.
     * Use this flag to transform them anyway.
     */
    SDWebImageTransformAnimatedImage = 1 << 9,

可以看到SDWebImage内部提供了对图像的Transform的能力,而最后一个接口提供了context参数,这个参数为我们提供了十分简洁的进行图片高级定制的能力。
SDWebImageContext的实现如下:

//  SDWebImageContext实际上是一个字典类型
typedef NSString * SDWebImageContextOption NS_EXTENSIBLE_STRING_ENUM;
typedef NSDictionary<SDWebImageContextOption, id> SDWebImageContext;

在define文件定义的后面我们可以找到如下定制类型的key:

/**
 A id<SDImageTransformer> instance which conforms `SDImageTransformer` protocol. It's used for image transform after the image load finished and store the transformed image to cache. If you provide one, it will ignore the `transformer` in manager and use provided one instead. (id<SDImageTransformer>)
 */
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageTransformer;

注释上面说明了,SDWebImage定义了id<SDImageTransformer>协议,通过实现此协议,你可以在图片加载完成后,对图片进行transform后缓存,本文我们将实现此协议来实现定制缓存。
协议实现如下:

@protocol SDImageTransformer <NSObject>
@required
/**
 For each transformer, it must contains its cache key to used to store the image cache or query from the cache. This key will be appened after the original cache key generated by URL or from user.
 @return The cache key to appended after the original cache key. Should not be nil.
 */
@property (nonatomic, copy, readonly, nonnull) NSString *transformerKey;

/**
 Transform the image to another image.
 @param image The image to be transformed
 @param key The cache key associated to the image
 @return The transformed image, or nil if transform failed
 */
- (nullable UIImage *)transformedImageWithImage:(nonnull UIImage *)image forKey:(nonnull NSString *)key;
@end

transformerKey 是你定制图片的缓存key,通过此url+transformerKey,你可以找到实现此定制的缓存图片

SDWebImage也提供了几种简单的处理方案:

2.1 Pipeline

顾名思义,你可以使用多种处理叠加生成最终处理图像进行缓存

#pragma mark - Pipeline
/**
 Pipeline transformer. Which you can bind multiple transformers together to let the image to be transformed one by one in order and generate the final image.
 @note Because transformers are lightweight, if you want to append or arrange transfomers, create another pipeline transformer instead. This class is considered as immutable.
 */
@interface SDImagePipelineTransformer : NSObject <SDImageTransformer>
/**
 All transformers in pipeline
 */
@property (nonatomic, copy, readonly, nonnull) NSArray<id<SDImageTransformer>> *transformers;
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)transformerWithTransformers:(nonnull NSArray<id<SDImageTransformer>> *)transformers;
@end
2.2 RoundCorner

为图片添加圆角

/**
 Image round corner transformer
 */
@interface SDImageRoundCornerTransformer: NSObject <SDImageTransformer>

/**
 The radius of each corner oval. Values larger than half the
 rectangle's width or height are clamped appropriately to
 half the width or height.
 */
@property (nonatomic, assign, readonly) CGFloat cornerRadius;

/**
 A bitmask value that identifies the corners that you want
 rounded. You can use this parameter to round only a subset
 of the corners of the rectangle.
 */
@property (nonatomic, assign, readonly) SDRectCorner corners;

/**
 The inset border line width. Values larger than half the rectangle's
 width or height are clamped appropriately to half the width
 or height.
 */
@property (nonatomic, assign, readonly) CGFloat borderWidth;

/**
 The border stroke color. nil means clear color.
 */
@property (nonatomic, strong, readonly, nullable) UIColor *borderColor;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)transformerWithRadius:(CGFloat)cornerRadius corners:(SDRectCorner)corners borderWidth:(CGFloat)borderWidth borderColor:(nullable UIColor *)borderColor;
@end

圆角转换支持设置边框和颜色,你也可以根据需要设置部分圆角,具体请看 SDRectCorner定义

2.3 Resizing

缩放处理,缩放是使用最为普遍的,通常情况下服务器端如果做得比较成熟的话,会提供大、中、小等图片链接,如果未做处理,并且返回的图片过大可以使用此方法处理

/**
 Image resizing transformer
 */
@interface SDImageResizingTransformer : NSObject <SDImageTransformer>
/**
 The new size to be resized, values should be positive.
 */
@property (nonatomic, assign, readonly) CGSize size;
/**
 The scale mode for image content.
 */
@property (nonatomic, assign, readonly) SDImageScaleMode scaleMode;
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)transformerWithSize:(CGSize)size scaleMode:(SDImageScaleMode)scaleMode;
@end
2.4 Cropping

进行图片裁剪

/**
 Image cropping transformer
 */
@interface SDImageCroppingTransformer : NSObject <SDImageTransformer>

/**
 Image's inner rect.
 */
@property (nonatomic, assign, readonly) CGRect rect;

- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)transformerWithRect:(CGRect)rect;

@end
2.5 Flipping

图片翻转

/**
 Image flipping transformer
 */
@interface SDImageFlippingTransformer : NSObject <SDImageTransformer>
/**
 YES to flip the image horizontally. ⇋
 */
@property (nonatomic, assign, readonly) BOOL horizontal;
/**
 YES to flip the image vertically. ⥯
 */
@property (nonatomic, assign, readonly) BOOL vertical;
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)transformerWithHorizontal:(BOOL)horizontal vertical:(BOOL)vertical;
@end
2.5 Rotation

旋转图片

/**
 Image rotation transformer
 */
@interface SDImageRotationTransformer : NSObject <SDImageTransformer>
/**
 Rotated radians in counterclockwise.⟲
 */
@property (nonatomic, assign, readonly) CGFloat angle;
/**
 YES: new image's size is extend to fit all content.
 NO: image's size will not change, content may be clipped.
 */
@property (nonatomic, assign, readonly) BOOL fitSize;
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)transformerWithAngle:(CGFloat)angle fitSize:(BOOL)fitSize;
@end
2.6 Image Blending

SDWebImage同样提供了图片颜色转换和滤镜等操作

/**
 Image tint color transformer
 */
@interface SDImageTintTransformer : NSObject <SDImageTransformer>
/**
 The tint color.
 */
@property (nonatomic, strong, readonly, nonnull) UIColor *tintColor;
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)transformerWithColor:(nonnull UIColor *)tintColor;
@end


/**
 Image blur effect transformer
 */
@interface SDImageBlurTransformer : NSObject <SDImageTransformer>
/**
 The radius of the blur in points, 0 means no blur effect.
 */
@property (nonatomic, assign, readonly) CGFloat blurRadius;
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)transformerWithRadius:(CGFloat)blurRadius;
@end

#if SD_UIKIT || SD_MAC
/**
 Core Image filter transformer
 */
@interface SDImageFilterTransformer: NSObject <SDImageTransformer>
/**
 The CIFilter to be applied to the image.
 */
@property (nonatomic, strong, readonly, nonnull) CIFilter *filter;
- (nonnull instancetype)init NS_UNAVAILABLE;
+ (nonnull instancetype)transformerWithFilter:(nonnull CIFilter *)filter;
@end

三、缩放定制

因为我们的APP只要求对图片进行缩放处理,所以这里我们结合APP依赖框架封装一套能够进行图片缩放的缓存接口
实现协议:

@interface SSImageResizingTransformer : NSObject <SDImageTransformer>
+ (instancetype)transformerWithSize:(CGSize)size scaleMode:(QMUIImageResizingMode)scaleMode;
@end


@interface SSImageResizingTransformer ()
@property (nonatomic, assign) CGSize size;
@property (nonatomic, assign) SDImageScaleMode scaleMode;
@end

@implementation SSImageResizingTransformer

+ (instancetype)transformerWithSize:(CGSize)size scaleMode:(QMUIImageResizingMode)scaleMode {
    SSImageResizingTransformer *transformer = [SSImageResizingTransformer new];
    transformer.size = size;
    transformer.scaleMode = scaleMode;
    return transformer;
}

- (NSString *)transformerKey {
    CGSize size = self.size;
    return [NSString stringWithFormat:@"SSImageResizingTransformer({%f,%f},%lu)", size.width, size.height, (unsigned long)self.scaleMode];
}

- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {
    if (!image) {
        return nil;
    }
    if (self.size.width <= 0 || self.size.height <= 0) {
        return image;
    }
    if (image.size.width < self.size.width && image.size.height < self.size.height){
        return image;
    }
    UIImage *scaledImage = [image qmui_imageResizedInLimitedSize:self.size resizingMode:QMUIImageResizingModeScaleAspectFit scale:UIScreen.mainScreen.scale];
    return scaledImage;
}

本文结合QMUI框架图片缩放接口对图片实现上述缩放,当图片小于缩放尺寸,或者缩放尺寸不合格则直接使用原始图片

四、接口封装

4.1 静态容器

使用静态容器存储申请的图片处理Transformer对象,避免重复申请

static NSMutableDictionary *SSImageContextContainer() {
    static NSMutableDictionary *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[NSMutableDictionary alloc]init];
    });
    return instance;
}

4.2 TransformerKey

NSString *SSTransformerKey(CGSize size, NSInteger scaleMode) {
    size.width = ceilf(size.width);
    size.height = ceilf(size.height);
    return [NSString stringWithFormat:@"SSImageResizingTransformer({%f,%f},%lu)", size.width, size.height, (unsigned long)scaleMode];
}

4.2 SDWebImageContext·

SDWebImageContext *SSGetWebImageContext(CGSize size, NSInteger scaleMode) {
    NSString *optionKey = SSTransformerKey(size,scaleMode);
    SDWebImageContext *context = HETSafeDictionaryInDict(SSImageContextContainer(),optionKey);
    if (context) {
        return context;
    }
    SSImageResizingTransformer *transformer = [SSImageResizingTransformer transformerWithSize:size scaleMode:scaleMode];
    if (transformer) {
        SDWebImageContext *imageContext = [SDWebImageContext dictionaryWithObject:transformer forKey:SDWebImageContextImageTransformer];
        [SSImageContextContainer() setValue:imageContext forKey:optionKey];
        return imageContext;
    }
    return nil;
}

4.4 实现UIImageView分类

当设置了size参数,第一次加载图片内部将会调用SSImageResizingTransformer对象对图片进行缩放,后续直接根据TransformerKey查询缓存,未设置size参数则缓存原始图片

@implementation UIImageView (SSWebImage)

- (void)SSSetImageWithURL:(nullable NSURL *)url {
    [self SSSetImageWithURL:url  placeHolderColor:nil];
}

- (void)SSSetImageWithURL:(nullable NSURL *)url
                     size:(CGSize)size
                     mode:(QMUIImageResizingMode)resizingMode {
    [self SSSetImageWithURL:url size:size mode:resizingMode  placeHolderColor:nil];
}

- (void)SSSetImageWithURL:(nullable NSURL *)url
                completed:(nullable SDExternalCompletionBlock)completedBlock{
    [self SSSetImageWithURL:url  placeHolderColor:nil completed:completedBlock];
}

- (void)SSSetImageWithURL:(nullable NSURL *)url
                     size:(CGSize)size
                     mode:(QMUIImageResizingMode)resizingMode
                completed:(nullable SDExternalCompletionBlock)completedBlock {
    [self SSSetImageWithURL:url  placeHolderColor:nil completed:completedBlock];
}


- (void)SSSetImageWithURL:(nullable NSURL *)url
         placeHolderColor:(nullable UIColor*)color {
    [self SSSetImageWithURL:url  placeHolderColor:color completed:nil];
}

- (void)SSSetImageWithURL:(nullable NSURL *)url
                     size:(CGSize)size
                     mode:(QMUIImageResizingMode)resizingMode
         placeHolderColor:(nullable UIColor*)color {
    [self SSSetImageWithURL:url size:size mode:resizingMode  placeHolderColor:color completed:nil];
}

- (void)SSSetImageWithURL:(nullable NSURL *)url
         placeHolderColor:(nullable UIColor*)color
                completed:(nullable SDExternalCompletionBlock)completedBlock {
    
    [self SSSetImageWithURL:url size:CGSizeZero mode:0  placeHolderColor:color completed:completedBlock];
}

- (void)SSSetImageWithURL:(nullable NSURL *)url
                     size:(CGSize)size
                     mode:(QMUIImageResizingMode)resizingMode
         placeHolderColor:(nullable UIColor*)color
                completed:(nullable SDExternalCompletionBlock)completedBlock {
    
    color  = color ? color : [UIColor qmui_colorWithHexString:@"#F5F5F5"];
    UIImage *placeHolderImage = [UIImage qmui_imageWithColor:color size:CGSizeMake(3, 3) cornerRadius:0];
    placeHolderImage = [placeHolderImage resizableImageWithCapInsets:UIEdgeInsetsMake(1, 1, 1, 1)];
    [self SSSetImageWithURL:url size:size mode:resizingMode placeholderImage:placeHolderImage completed:completedBlock];
}

- (void)SSSetImageWithURL:(nullable NSURL *)url
         placeholderImage:(nullable UIImage *)placeholder {
    [self SSSetImageWithURL:url placeholderImage:placeholder completed:nil];
}



- (void)SSSetImageWithURL:(nullable NSURL *)url
         placeholderImage:(nullable UIImage *)placeholder
                completed:(nullable SDExternalCompletionBlock)completedBlock{
    [self SSSetImageWithURL:url size:CGSizeZero mode:0 placeholderImage:placeholder completed:completedBlock];
}

- (void)SSSetImageWithURL:(nullable NSURL *)url
                     size:(CGSize)size
                     mode:(QMUIImageResizingMode)resizingMode
         placeholderImage:(nullable UIImage *)placeholder  {
    [self SSSetImageWithURL:url size:size mode:resizingMode placeholderImage:placeholder completed:nil];
}


- (void)SSSetImageWithURL:(nullable NSURL *)url
                     size:(CGSize)size
                     mode:(QMUIImageResizingMode)resizingMode
         placeholderImage:(nullable UIImage *)placeholder
                completed:(nullable SDExternalCompletionBlock)completedBlock{
    [self SSSetImageWithURL:url size:size mode:resizingMode placeholderImage:placeholder  options:(SDWebImageRetryFailed | SDWebImageAllowInvalidSSLCertificates)  completed:completedBlock];
}

- (void)SSSetImageWithURL:(nullable NSURL *)url
                     size:(CGSize)size
                     mode:(QMUIImageResizingMode)resizingMode
         placeholderImage:(nullable UIImage *)placeholder
                  options:(SDWebImageOptions)options
                completed:(nullable SDExternalCompletionBlock)completedBlock{
    [self SSSetImageWithURL:url size:size mode:resizingMode placeholderImage:placeholder  options:options  progress:nil completed:completedBlock];
    
}

- (void)SSSetImageWithURL:(nullable NSURL *)url
                     size:(CGSize)size
                     mode:(QMUIImageResizingMode)resizingMode
         placeholderImage:(nullable UIImage *)placeholder
                  options:(SDWebImageOptions)options
                 progress:(nullable SDImageLoaderProgressBlock)progressBlock
                completed:(nullable SDExternalCompletionBlock)completedBlock{
    SDWebImageContext *imageContext = nil;
    if (!CGSizeEqualToSize(size, CGSizeZero)) {
        imageContext = SSGetWebImageContext(size, resizingMode);
    }
    [self sd_setImageWithURL:url placeholderImage:placeholder options:options context:imageContext progress:nil completed:completedBlock];
}

六、小节

本文我们只是基于SDWebImage框架做了图片缩放缓存处理,你可以根据需要实现SDImageTransformer协议对图片进行你自己的业务处理,具体不在讲述。

目前有个疑问就是定制处理会不会导致图片重复从网络加载,如果服务器提供的图片较大,而我们需要两个规格的缩放处理,首次加载后不知道SDWebImage是不是同时也做了大图缓存,使用另外一种规格再次访问时直接提取大图缓存定制小图,还是从网络下载后再进行小图定制,后面再去阅读下源代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335