Separate the image class and coder class's protocol. Make this two more modular

This commit is contained in:
DreamPiggy 2018-03-29 03:36:21 +08:00
parent 16d39e4982
commit 920d61f47e
5 changed files with 61 additions and 73 deletions

View File

@ -7,51 +7,25 @@
*/
#import "SDWebImageCompat.h"
#import "NSData+ImageContentType.h"
#import "SDWebImageCoder.h"
@protocol SDWebImageAnimatedCoder;
@protocol SDAnimatedImage <NSObject>
/**
This is the protocol for SDAnimatedImage class only but not for SDWebImageAnimatedCoder. If you want to provide a custom animated image class with full advanced function, you can conform to this instead of the base protocol.
*/
@protocol SDAnimatedImage <SDAnimatedImageProvider>
@required
/**
The original animated image data for current image. If current image is not an animated format, return nil.
We may use this method to grab back the original image data if need, such as NSCoding or compare.
Initializes the image with an animated coder. You can use the coder to decode the image frame later.
@note Normally we use `initWithData:scale:` to create custom animated image class. However, for progressive image decoding, we will use this instead.
@return The animated image data
@param animatedCoder An animated coder which conform `SDWebImageAnimatedCoder` protocol
@param scale The scale factor to assume when interpreting the image data. Applying a scale factor of 1.0 results in an image whose size matches the pixel-based dimensions of the image. Applying a different scale factor changes the size of the image as reported by the `size` property.
@return An initialized object
*/
- (nullable NSData *)animatedImageData;
- (nullable instancetype)initWithAnimatedCoder:(nonnull id<SDWebImageAnimatedCoder>)animatedCoder scale:(CGFloat)scale;
/**
Total animated frame count.
It the frame count is less than 1, then the methods below will be ignored.
@return Total animated frame count.
*/
- (NSUInteger)animatedImageFrameCount;
/**
Animation loop count, 0 means infinite looping.
@return Animation loop count
*/
- (NSUInteger)animatedImageLoopCount;
/**
Returns the frame image from a specified index.
@note The index maybe randomly if one image was set to different imageViews, keep it re-entrant. (It's not recommend to store the images into array because it's memory consuming)
@param index Frame index (zero based).
@return Frame's image
*/
- (nullable UIImage *)animatedImageFrameAtIndex:(NSUInteger)index;
/**
Returns the frames's duration from a specified index.
@note The index maybe randomly if one image was set to different imageViews, keep it re-entrant. (It's recommend to store the durations into array because it's not memory-consuming)
@param index Frame index (zero based).
@return Frame's duration
*/
- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index;
// These methods are for SDAnimatedImage class only but not for SDWebImageAnimatedCoder.
@optional
/**
Pre-load all animated image frame into memory. Then later frame image request can directly return the frame for index without decoding.
@ -71,16 +45,6 @@
*/
- (BOOL)isAllFramesLoaded;
/**
Initializes the image with an animated coder. You can use the coder to decode the image frame later.
@note Normally we use `initWithData:scale:` to create custom animated image class. So you can implement your custom class without our built-in coder.
@param animatedCoder An animated coder which conform `SDWebImageAnimatedCoder` protocol
@param scale The scale factor to assume when interpreting the image data. Applying a scale factor of 1.0 results in an image whose size matches the pixel-based dimensions of the image. Applying a different scale factor changes the size of the image as reported by the `size` property.
@return An initialized object
*/
- (nullable instancetype)initWithAnimatedCoder:(nonnull id<SDWebImageAnimatedCoder>)animatedCoder scale:(CGFloat)scale;
@end
@interface SDAnimatedImage : UIImage <SDAnimatedImage>

View File

@ -282,9 +282,6 @@ static NSArray *SDBundlePreferredScales() {
if (!data || data.length == 0) {
return nil;
}
if (scale <= 0) {
scale = 1;
}
data = [data copy]; // avoid mutable data
id<SDWebImageAnimatedCoder> animatedCoder = nil;
for (id<SDWebImageCoder>coder in [SDWebImageCodersManager sharedManager].coders) {
@ -298,24 +295,7 @@ static NSArray *SDBundlePreferredScales() {
if (!animatedCoder) {
return nil;
}
UIImage *image = [animatedCoder animatedImageFrameAtIndex:0];
if (!image) {
return nil;
}
#if SD_MAC
self = [super initWithCGImage:image.CGImage size:NSZeroSize];
#else
self = [super initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
#endif
if (self) {
_coder = animatedCoder;
#if SD_MAC
_scale = scale;
#endif
SDImageFormat format = [NSData sd_imageFormatForImageData:data];
_animatedImageFormat = format;
}
return self;
return [self initWithAnimatedCoder:animatedCoder scale:scale];
}
- (instancetype)initWithAnimatedCoder:(id<SDWebImageAnimatedCoder>)animatedCoder scale:(CGFloat)scale {

View File

@ -9,7 +9,6 @@
#import <Foundation/Foundation.h>
#import "SDWebImageCompat.h"
#import "NSData+ImageContentType.h"
#import "SDAnimatedImage.h"
typedef NSString * SDWebImageCoderOption NS_STRING_ENUM;
typedef NSDictionary<SDWebImageCoderOption, id> SDWebImageCoderOptions;
@ -118,11 +117,56 @@ FOUNDATION_EXPORT SDWebImageCoderOption _Nonnull const SDWebImageCoderEncodeComp
@end
/**
This is the animated image protocol to provide the basic function for animated image rendering. It's adopted by `SDAnimatedImage` and `SDWebImageAnimatedCoder`
*/
@protocol SDAnimatedImageProvider <NSObject>
@required
/**
The original animated image data for current image. If current image is not an animated format, return nil.
We may use this method to grab back the original image data if need, such as NSCoding or compare.
@return The animated image data
*/
- (nullable NSData *)animatedImageData;
/**
Total animated frame count.
It the frame count is less than 1, then the methods below will be ignored.
@return Total animated frame count.
*/
- (NSUInteger)animatedImageFrameCount;
/**
Animation loop count, 0 means infinite looping.
@return Animation loop count
*/
- (NSUInteger)animatedImageLoopCount;
/**
Returns the frame image from a specified index.
@note The index maybe randomly if one image was set to different imageViews, keep it re-entrant. (It's not recommend to store the images into array because it's memory consuming)
@param index Frame index (zero based).
@return Frame's image
*/
- (nullable UIImage *)animatedImageFrameAtIndex:(NSUInteger)index;
/**
Returns the frames's duration from a specified index.
@note The index maybe randomly if one image was set to different imageViews, keep it re-entrant. (It's recommend to store the durations into array because it's not memory-consuming)
@param index Frame index (zero based).
@return Frame's duration
*/
- (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index;
@end
/**
This is the animated image coder protocol for custom animated image class like `SDAnimatedImage`. Through it inherit from `SDWebImageCoder`. We currentlly only use the method `canDecodeFromData:` to detect the proper coder for specify animated image format.
*/
@protocol SDWebImageAnimatedCoder <SDWebImageCoder, SDAnimatedImage>
@protocol SDWebImageAnimatedCoder <SDWebImageCoder, SDAnimatedImageProvider>
@required
/**

View File

@ -50,7 +50,7 @@ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextCustom
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextCustomTransformer;
/**
A Class object which the instance is a `UIImage/NSImage` subclass and adopt `SDAnimatedImage` protocol. We will call `initWithData:scale:` to create the instance (or `initWithAnimatedCoder:sclae` when using progressive download) . If the instance create failed, fallback to normal `UIImage/NSImage`.
A Class object which the instance is a `UIImage/NSImage` subclass and adopt `SDAnimatedImage` protocol. We will call `initWithData:scale:` to create the instance (or `initWithAnimatedCoder:scale` when using progressive download) . If the instance create failed, fallback to normal `UIImage/NSImage`.
This can be used to improve animated images rendering performance (especially memory usage on big animated images) with `SDAnimatedImageView` (Class).
*/
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextAnimatedImageClass;

View File

@ -365,7 +365,7 @@ didReceiveResponse:(NSURLResponse *)response
UIImage *image;
if ([self.context valueForKey:SDWebImageContextAnimatedImageClass]) {
Class animatedImageClass = [self.context valueForKey:SDWebImageContextAnimatedImageClass];
if ([animatedImageClass isSubclassOfClass:[UIImage class]] && [animatedImageClass conformsToProtocol:@protocol(SDAnimatedImage)] && [animatedImageClass instancesRespondToSelector:@selector(initWithAnimatedCoder:scale:)] && [self.progressiveCoder conformsToProtocol:@protocol(SDWebImageAnimatedCoder)]) {
if ([animatedImageClass isSubclassOfClass:[UIImage class]] && [animatedImageClass conformsToProtocol:@protocol(SDAnimatedImage)] && [self.progressiveCoder conformsToProtocol:@protocol(SDWebImageAnimatedCoder)]) {
CGFloat scale = SDImageScaleForKey(self.cacheKey);
image = [[animatedImageClass alloc] initWithAnimatedCoder:(id<SDWebImageAnimatedCoder>)self.progressiveCoder scale:scale];
}