Adopt the transformer to cache & manager. Use a new context option SDWebImageContextCustomTransformer to bind the transformer

Drop old way of delegate method for transformer. Add two new delegate methods to allow advanced use case after we remove that.
This commit is contained in:
DreamPiggy 2018-02-13 18:30:25 +08:00
parent b4ea87f6c5
commit 464d725368
12 changed files with 52 additions and 35 deletions

View File

@ -406,12 +406,12 @@
32F7C0812030719600873181 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C07C2030719600873181 /* UIImage+Transform.m */; };
32F7C0822030719600873181 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C07C2030719600873181 /* UIImage+Transform.m */; };
32F7C0832030719600873181 /* UIImage+Transform.m in Sources */ = {isa = PBXBuildFile; fileRef = 32F7C07C2030719600873181 /* UIImage+Transform.m */; };
32F7C0842030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
32F7C0852030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
32F7C0862030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
32F7C0872030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
32F7C0882030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
32F7C0892030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; };
32F7C0842030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; settings = {ATTRIBUTES = (Public, ); }; };
32F7C0852030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; settings = {ATTRIBUTES = (Public, ); }; };
32F7C0862030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; settings = {ATTRIBUTES = (Public, ); }; };
32F7C0872030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; settings = {ATTRIBUTES = (Public, ); }; };
32F7C0882030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; settings = {ATTRIBUTES = (Public, ); }; };
32F7C0892030719600873181 /* UIImage+Transform.h in Headers */ = {isa = PBXBuildFile; fileRef = 32F7C07D2030719600873181 /* UIImage+Transform.h */; settings = {ATTRIBUTES = (Public, ); }; };
4314D1231D0E0E3B004B36C9 /* SDImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 53922D86148C56230056699D /* SDImageCache.m */; };
4314D1311D0E0E3B004B36C9 /* SDWebImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 53922D8C148C56230056699D /* SDWebImageDownloader.m */; };
4314D1341D0E0E3B004B36C9 /* UIImage+WebP.m in Sources */ = {isa = PBXBuildFile; fileRef = 53EDFB921762547C00698166 /* UIImage+WebP.m */; };

View File

@ -34,7 +34,12 @@ typedef NS_OPTIONS(NSUInteger, SDImageCacheOptions) {
/**
* By default, we query the memory cache synchronously, disk cache asynchronously. This mask can force to query disk cache synchronously.
*/
SDImageCacheQueryDiskSync = 1 << 1
SDImageCacheQueryDiskSync = 1 << 1,
/**
* We usually don't apply transform on animated images as most transformers could not manage animated images.
* Use this flag to transform them anyway.
*/
SDImageCacheTransformAnimatedImage = 1 << 2,
};
typedef void(^SDCacheQueryCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType);

View File

@ -10,6 +10,7 @@
#import <CommonCrypto/CommonDigest.h>
#import "NSImage+Additions.h"
#import "SDWebImageCodersManager.h"
#import "SDWebImageTransformer.h"
#define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
#define UNLOCK(lock) dispatch_semaphore_signal(lock);
@ -532,11 +533,18 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
diskImage = image;
cacheType = SDImageCacheTypeMemory;
} else if (diskData) {
NSString *cacheKey = key;
if ([context valueForKey:SDWebImageContextCustomTransformer]) {
// grab the transformed disk image if transformer provided
id<SDWebImageTransformer> transformer = [context valueForKey:SDWebImageContextCustomTransformer];
NSString *transformerKey = [transformer transformerKey];
cacheKey = [[key stringByAppendingString:SDWebImageTransformerKeySeparator] stringByAppendingString:transformerKey];
}
// decode image data only if in-memory cache missed
diskImage = [self diskImageForKey:key data:diskData];
diskImage = [self diskImageForKey:cacheKey data:diskData];
if (diskImage && self.config.shouldCacheImagesInMemory) {
NSUInteger cost = SDCacheCostForImage(diskImage);
[self.memCache setObject:diskImage forKey:key cost:cost];
[self.memCache setObject:diskImage forKey:cacheKey cost:cost];
}
}

View File

@ -20,3 +20,8 @@ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextSetIma
A SDWebImageManager instance to control the image download and cache process using in UIImageView+WebCache category and likes. If not provided, use the shared manager (SDWebImageManager)
*/
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextCustomManager;
/**
A id<SDWebImageTransformer> instance which conforms SDWebImageTransformer protocol. It's used for image transform after the image load finished and store the transformed image to cache. (id<SDWebImageTransformer>)
*/
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextCustomTransformer;

View File

@ -10,3 +10,4 @@
SDWebImageContextOption const SDWebImageContextSetImageGroup = @"setImageGroup";
SDWebImageContextOption const SDWebImageContextCustomManager = @"customManager";
SDWebImageContextOption const SDWebImageContextCustomTransformer = @"customTransformer";

View File

@ -76,8 +76,7 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
SDWebImageDelayPlaceholder = 1 << 9,
/**
* We usually don't call transformDownloadedImage delegate method on animated images,
* as most transformation code would mangle it.
* 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 << 10,
@ -115,7 +114,7 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
/**
* By default, when you use `SDWebImageTransition` to do some view transition after the image load finished, this transition is only applied for image download from the network. This mask can force to apply view transition for memory and disk cache as well.
*/
SDWebImageForceTransition = 1 << 16
SDWebImageForceTransition = 1 << 16,
};
typedef void(^SDExternalCompletionBlock)(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL);
@ -141,7 +140,7 @@ typedef NSData * _Nullable(^SDWebImageCacheSerializerBlock)(UIImage * _Nonnull i
*
* @return Return NO to prevent the downloading of the image on cache misses. If not implemented, YES is implied.
*/
- (BOOL)imageManager:(nonnull SDWebImageManager *)imageManager shouldDownloadImageForURL:(nullable NSURL *)imageURL;
- (BOOL)imageManager:(nonnull SDWebImageManager *)imageManager shouldDownloadImageForURL:(nonnull NSURL *)imageURL;
/**
* Controls the complicated logic to mark as failed URLs when download error occur.
@ -153,18 +152,6 @@ typedef NSData * _Nullable(^SDWebImageCacheSerializerBlock)(UIImage * _Nonnull i
*/
- (BOOL)imageManager:(nonnull SDWebImageManager *)imageManager shouldBlockFailedURL:(nonnull NSURL *)imageURL withError:(nonnull NSError *)error;
/**
* 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
/**

View File

@ -9,6 +9,7 @@
#import "SDWebImageManager.h"
#import "NSImage+Additions.h"
#import <objc/message.h>
#import "SDWebImageTransformer.h"
@interface SDWebImageCombinedOperation : NSObject <SDWebImageOperation>
@ -153,6 +154,7 @@
SDImageCacheOptions cacheOptions = 0;
if (options & SDWebImageQueryDataWhenInMemory) cacheOptions |= SDImageCacheQueryDataWhenInMemory;
if (options & SDWebImageQueryDiskSync) cacheOptions |= SDImageCacheQueryDiskSync;
if (options & SDWebImageTransformAnimatedImage) cacheOptions |= SDImageCacheTransformAnimatedImage;
__weak SDWebImageCombinedOperation *weakOperation = operation;
operation.cacheOperation = [self.imageCache queryCacheOperationForKey:key options:cacheOptions done:^(UIImage *cachedImage, NSData *cachedData, SDImageCacheType cacheType) {
@ -238,11 +240,13 @@
if (options & SDWebImageRefreshCached && cachedImage && !downloadedImage) {
// Image refresh hit the NSURLCache cache, do not call the completion block
} else if (downloadedImage && (!downloadedImage.images || (options & SDWebImageTransformAnimatedImage)) && [self.delegate respondsToSelector:@selector(imageManager:transformDownloadedImage:withURL:)]) {
} else if (downloadedImage && (!downloadedImage.images || (options & SDWebImageTransformAnimatedImage)) && [context valueForKey:SDWebImageContextCustomTransformer]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
UIImage *transformedImage = [self.delegate imageManager:self transformDownloadedImage:downloadedImage withURL:url];
id<SDWebImageTransformer> transformer = [context valueForKey:SDWebImageContextCustomTransformer];
UIImage *transformedImage = [transformer transformedImageWithImage:downloadedImage forKey:key];
if (transformedImage && finished) {
NSString *transformerKey = [transformer transformerKey];
NSString *cacheKey = [[key stringByAppendingString:SDWebImageTransformerKeySeparator] stringByAppendingString:transformerKey];
BOOL imageWasTransformed = ![transformedImage isEqual:downloadedImage];
NSData *cacheData;
// pass nil if the image was transformed, so we can recalculate the data from the image
@ -251,7 +255,7 @@
} else {
cacheData = (imageWasTransformed ? nil : downloadedData);
}
[self.imageCache storeImage:transformedImage imageData:cacheData forKey:key toDisk:cacheOnDisk completion:nil];
[self.imageCache storeImage:transformedImage imageData:cacheData forKey:cacheKey toDisk:cacheOnDisk completion:nil];
}
[self callCompletionBlockForOperation:strongSubOperation completion:completedBlock image:transformedImage data:downloadedData error:nil cacheType:SDImageCacheTypeNone finished:finished url:url];

View File

@ -39,6 +39,9 @@
#pragma mark - Pipeline
// Separator for different transformerKey, for example, `image.png` |> flip(YES,NO) |> rotate(pi/4,YES) => 'image-SDWebImageFlippingTransformer(1,0)-SDWebImageRotationTransformer(0.78539816339,1).png'
FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageTransformerKeySeparator;
// Pipeline transformer. Which you can bind multiple transformers together to let the image to be transformed one by one and generate the final image.
@interface SDWebImagePipelineTransformer : NSObject <SDWebImageTransformer>

View File

@ -50,6 +50,8 @@
@end
NSString * const SDWebImageTransformerKeySeparator = @"-";
@interface SDWebImagePipelineTransformer ()
@property (nonatomic, copy, readwrite, nonnull) NSArray<id<SDWebImageTransformer>> *transformers;
@ -78,7 +80,7 @@
[cacheKeys addObject:cacheKey];
}];
return [cacheKeys componentsJoinedByString:@"@"];
return [cacheKeys componentsJoinedByString:SDWebImageTransformerKeySeparator];
}
- (UIImage *)transformedImageWithImage:(UIImage *)image forKey:(NSString *)key {

View File

@ -39,7 +39,7 @@ typedef NS_OPTIONS(NSUInteger, SDRectCorner) {
The image content will be changed with the scale mode.
@param size The new size to be scaled, values should be positive.
@param contentMode The scale mode for image content.
@param scaleMode The scale mode for image content.
@return The new image with the given size.
*/
- (nullable UIImage *)sd_resizedImageWithSize:(CGSize)size scaleMode:(SDImageScaleMode)scaleMode;
@ -47,7 +47,7 @@ typedef NS_OPTIONS(NSUInteger, SDRectCorner) {
/**
Returns a new image which is cropped from this image.
@param cropRect Image's inner rect.
@param rect Image's inner rect.
@return The new image with the cropping rect.
*/
- (nullable UIImage *)sd_croppedImageWithRect:(CGRect)rect;
@ -75,7 +75,7 @@ typedef NS_OPTIONS(NSUInteger, SDRectCorner) {
/**
Returns a new rotated image (relative to the center).
@param radians Rotated radians in counterclockwise.
@param angle Rotated radians in counterclockwise.
@param fitSize YES: new image's size is extend to fit all content.
NO: image's size will not change, content may be clipped.
@return The new image with the rotation.

View File

@ -149,13 +149,13 @@ static CGRect SDCGRectFitWithScaleMode(CGRect rect, CGSize size, SDImageScaleMod
}
#if SD_MAC
@interface NSBezierPath (Compatibility)
@interface NSBezierPath (Additions)
+ (instancetype)bezierPathWithRoundedRect:(NSRect)rect byRoundingCorners:(SDRectCorner)corners cornerRadius:(CGFloat)cornerRadius;
@end
@implementation NSBezierPath (Compatibility)
@implementation NSBezierPath (Additions)
+ (instancetype)bezierPathWithRoundedRect:(NSRect)rect byRoundingCorners:(SDRectCorner)corners cornerRadius:(CGFloat)cornerRadius {
NSBezierPath *path = [NSBezierPath bezierPath];

View File

@ -37,6 +37,8 @@ FOUNDATION_EXPORT const unsigned char WebImageVersionString[];
#import <SDWebImage/SDWebImageDownloader.h>
#import <SDWebImage/SDWebImageTransition.h>
#import <SDWebImage/SDWebImageIndicator.h>
#import <SDWebImage/SDWebImageTransformer.h>
#import <SDWebImage/UIImage+Transform.h>
#if SD_MAC || SD_UIKIT
#import <SDWebImage/MKAnnotationView+WebCache.h>