SDWebImage扩展-图像处理
SDWebImage 大家都用过,加载网络图片的一个类库,非常好用,可是在一些比较特殊的情况下就会出现一些不足,如下情况:
app 很多地方的网络图片都需要在显示时候进行描边处理或者圆角处理(直接设置layer圆角,多了会导致table卡顿,所以通常是在图片上做手脚),而图片的加载显示刚好用的SDWebImage,这时候问题就来了,SDWebImage缓存的图片是原图,每次在显示时候对图片进行加工然后显示,其实是很糟糕的做法,完全可以在缓存图片前处理好,显示时候直接拿来用。
这里介绍的就是未处理这个功能,新版不知道是不是支持这种情况。
怎么搞呢,分析源码吧,网上很多介绍很详细的文章,我这边简单说一下:
关键函数如下图:
下载函数
这个函数是获取一手图片文件的地方,代码还有点多
原始数据
做法很简单,就是在这个方法的这个block 获取到图片时候用另外一个block把图片传到调用的地方,加工后再返回回来,缓存这个新图片,如图:
图片处理替换
这样基本达满足前边描述的情况了,
但是如果这一张图片在多个地方使用,而且这些个地方对图片的处理有事不一样的时候就不行了,比方有的描边有的圆角。
怎么办呢,
在设置图片的地方再加个参数key来标记图片处理操作类型
这个处理起来比较简单,只需要搞一下原本缓存的key就可以了,原本是酱紫的:
缓存key
搞成酱紫就可以了:
新缓存key
然后设置函数把两个新的参数补上去救ok了,为了不影响原来的结构,新建了一个分类,新增了这么个下载函数如下图:
新函数
然后扩展一下设置图片的方法就完美了如下:
- (void)sd_setImageWithURL:(NSURL *)url processKey:(NSString*)processKey processBlock:(SDWebImageProcessBlock)processBlock {
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:nil processKey:processKey processBlock:processBlock];
}
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder processKey:(NSString*)processKey processBlock:(SDWebImageProcessBlock)processBlock{
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:nil processKey:processKey processBlock:processBlock] ;
}
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options processKey:(NSString*)processKey processBlock:(SDWebImageProcessBlock)processBlock{
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:nil processKey:processKey processBlock:processBlock];
}
- (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock processKey:(NSString*)processKey processBlock:(SDWebImageProcessBlock)processBlock{
[self sd_setImageWithURL:url placeholderImage:nil options:0 progress:nil completed:completedBlock processKey:processKey processBlock:processBlock];
}
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock processKey:(NSString*)processKey processBlock:(SDWebImageProcessBlock)processBlock{
[self sd_setImageWithURL:url placeholderImage:placeholder options:0 progress:nil completed:completedBlock processKey:processKey processBlock:processBlock];
}
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock processKey:(NSString*)processKey processBlock:(SDWebImageProcessBlock)processBlock{
[self sd_setImageWithURL:url placeholderImage:placeholder options:options progress:nil completed:completedBlock processKey:processKey processBlock:processBlock];
}
设置函数里的总入口改一下
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock processKey:(NSString*)processKey processBlock:(SDWebImageProcessBlock)processBlock {
[self sd_cancelCurrentImageLoad];
objc_setAssociatedObject(self, &imageURLKey_Process, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
if (!(options & SDWebImageDelayPlaceholder)) {
dispatch_main_async_safe(^{
self.image = placeholder;
});
}
if (url) {
// check if activityView is enabled or not
if ([self showActivityIndicatorView]) {
[self addActivityIndicator];
}
__weak __typeof(self)wself = self;
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
[wself removeActivityIndicator];
if (!wself) return;
dispatch_main_sync_safe(^{
if (!wself) return;
if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock)
{
completedBlock(image, error, cacheType, url);
return;
}
else if (image) {
wself.image = image;
[wself setNeedsLayout];
} else {
if ((options & SDWebImageDelayPlaceholder)) {
wself.image = placeholder;
[wself setNeedsLayout];
}
}
if (completedBlock && finished) {
completedBlock(image, error, cacheType, url);
}
});
} processKey:processKey processBlock:processBlock];
[self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];
} else {
dispatch_main_async_safe(^{
[self removeActivityIndicator];
if (completedBlock) {
NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
completedBlock(nil, error, SDImageCacheTypeNone, url);
}
});
}
}
然后声明一下头文件就好了,
.m文件遇到一些属性找不到弄个延展引进来就好了如下:
属性引入
有点多,为了方便,没办法,人家本来就这么多,oc下只能一个个搞。
这么一来就可以完美满足前边描述的情况了。
ps:SDWebImage 版本 3.8.2,后边的情况不知道如何,就还没更新。