Replace conformsToProtocol call with appropriate respondsToSelector check

This effect API called with multiple times, for some one-time setup and important check, the conformsToProtocol is remained
This commit is contained in:
DreamPiggy 2022-11-08 19:45:21 +08:00
parent 6a9b578369
commit 9aa27b61e8
8 changed files with 38 additions and 70 deletions

View File

@ -471,7 +471,7 @@
{
if ([image.class conformsToProtocol:@protocol(SDAnimatedImage)] && image.sd_isIncremental && [image respondsToSelector:@selector(animatedCoder)]) {
id<SDAnimatedImageCoder> animatedCoder = [(id<SDAnimatedImage>)image animatedCoder];
if ([animatedCoder conformsToProtocol:@protocol(SDProgressiveImageCoder)]) {
if ([animatedCoder respondsToSelector:@selector(initIncrementalWithOptions:)]) {
return (id<SDAnimatedImageCoder, SDProgressiveImageCoder>)animatedCoder;
}
}

View File

@ -245,7 +245,7 @@ static NSString * _defaultDiskCacheDirectory;
dispatch_async(self.ioQueue, ^{
@autoreleasepool {
NSData *data = imageData;
if (!data && [image conformsToProtocol:@protocol(SDAnimatedImage)]) {
if (!data && [image respondsToSelector:@selector(animatedImageData)]) {
// If image is custom animated image class, prefer its original animated data
data = [((id<SDAnimatedImage>)image) animatedImageData];
}
@ -440,8 +440,7 @@ static NSString * _defaultDiskCacheDirectory;
if (image) {
if (options & SDImageCacheDecodeFirstFrameOnly) {
// Ensure static image
Class animatedImageClass = image.class;
if (image.sd_isAnimated || ([animatedImageClass isSubclassOfClass:[UIImage class]] && [animatedImageClass conformsToProtocol:@protocol(SDAnimatedImage)])) {
if (image.sd_isAnimated) {
#if SD_MAC
image = [[NSImage alloc] initWithCGImage:image.CGImage scale:image.scale orientation:kCGImagePropertyOrientationUp];
#else
@ -574,8 +573,7 @@ static NSString * _defaultDiskCacheDirectory;
if (image) {
if (options & SDImageCacheDecodeFirstFrameOnly) {
// Ensure static image
Class animatedImageClass = image.class;
if (image.sd_isAnimated || ([animatedImageClass isSubclassOfClass:[UIImage class]] && [animatedImageClass conformsToProtocol:@protocol(SDAnimatedImage)])) {
if (image.sd_isAnimated) {
#if SD_MAC
image = [[NSImage alloc] initWithCGImage:image.CGImage scale:image.scale orientation:kCGImagePropertyOrientationUp];
#else

View File

@ -94,10 +94,8 @@ UIImage * _Nullable SDImageCacheDecodeImageData(NSData * _Nonnull imageData, NSS
CGFloat scale = [coderOptions[SDImageCoderDecodeScaleFactor] doubleValue];
// Grab the image coder
id<SDImageCoder> imageCoder;
if ([context[SDWebImageContextImageCoder] conformsToProtocol:@protocol(SDImageCoder)]) {
imageCoder = context[SDWebImageContextImageCoder];
} else {
id<SDImageCoder> imageCoder = context[SDWebImageContextImageCoder];
if (!imageCoder) {
imageCoder = [SDImageCodersManager sharedManager];
}
@ -128,12 +126,6 @@ UIImage * _Nullable SDImageCacheDecodeImageData(NSData * _Nonnull imageData, NSS
if (lazyDecode) {
// lazyDecode = NO means we should not forceDecode, highest priority
shouldDecode = NO;
} else if ([image.class conformsToProtocol:@protocol(SDAnimatedImage)]) {
// `SDAnimatedImage` do not decode
shouldDecode = NO;
} else if (image.sd_isAnimated) {
// animated image do not decode
shouldDecode = NO;
}
if (shouldDecode) {
image = [SDImageCoderHelper decodedImageWithImage:image];

View File

@ -47,10 +47,8 @@ UIImage * _Nullable SDImageLoaderDecodeImageData(NSData * _Nonnull imageData, NS
CGFloat scale = [coderOptions[SDImageCoderDecodeScaleFactor] doubleValue];
// Grab the image coder
id<SDImageCoder> imageCoder;
if ([context[SDWebImageContextImageCoder] conformsToProtocol:@protocol(SDImageCoder)]) {
imageCoder = context[SDWebImageContextImageCoder];
} else {
id<SDImageCoder> imageCoder = context[SDWebImageContextImageCoder];
if (!imageCoder) {
imageCoder = [SDImageCodersManager sharedManager];
}
@ -81,12 +79,6 @@ UIImage * _Nullable SDImageLoaderDecodeImageData(NSData * _Nonnull imageData, NS
if (lazyDecode) {
// lazyDecode = NO means we should not forceDecode, highest priority
shouldDecode = NO;
} else if ([image.class conformsToProtocol:@protocol(SDAnimatedImage)]) {
// `SDAnimatedImage` do not decode
shouldDecode = NO;
} else if (image.sd_isAnimated) {
// animated image do not decode
shouldDecode = NO;
}
if (shouldDecode) {
image = [SDImageCoderHelper decodedImageWithImage:image];
@ -120,7 +112,7 @@ UIImage * _Nullable SDImageLoaderDecodeProgressiveImageData(NSData * _Nonnull im
if (!progressiveCoder) {
id<SDProgressiveImageCoder> imageCoder = context[SDWebImageContextImageCoder];
// Check the progressive coder if provided
if ([imageCoder conformsToProtocol:@protocol(SDProgressiveImageCoder)]) {
if ([imageCoder respondsToSelector:@selector(initIncrementalWithOptions:)]) {
progressiveCoder = [[[imageCoder class] alloc] initIncrementalWithOptions:coderOptions];
} else {
// We need to create a new instance for progressive decoding to avoid conflicts
@ -143,7 +135,7 @@ UIImage * _Nullable SDImageLoaderDecodeProgressiveImageData(NSData * _Nonnull im
if (!decodeFirstFrame) {
// check whether we should use `SDAnimatedImage`
Class animatedImageClass = context[SDWebImageContextAnimatedImageClass];
if ([animatedImageClass isSubclassOfClass:[UIImage class]] && [animatedImageClass conformsToProtocol:@protocol(SDAnimatedImage)] && [progressiveCoder conformsToProtocol:@protocol(SDAnimatedImageCoder)]) {
if ([animatedImageClass isSubclassOfClass:[UIImage class]] && [animatedImageClass conformsToProtocol:@protocol(SDAnimatedImage)] && [progressiveCoder respondsToSelector:@selector(animatedImageFrameAtIndex:)]) {
image = [[animatedImageClass alloc] initWithAnimatedCoder:(id<SDAnimatedImageCoder>)progressiveCoder scale:scale];
if (image) {
// Progressive decoding does not preload frames
@ -164,12 +156,6 @@ UIImage * _Nullable SDImageLoaderDecodeProgressiveImageData(NSData * _Nonnull im
if (lazyDecode) {
// lazyDecode = NO means we should not forceDecode, highest priority
shouldDecode = NO;
} else if ([image.class conformsToProtocol:@protocol(SDAnimatedImage)]) {
// `SDAnimatedImage` do not decode
shouldDecode = NO;
} else if (image.sd_isAnimated) {
// animated image do not decode
shouldDecode = NO;
}
if (shouldDecode) {
image = [SDImageCoderHelper decodedImageWithImage:image];

View File

@ -353,9 +353,7 @@ static void * SDWebImageDownloaderContext = &SDWebImageDownloaderContext;
// Operation Class
Class operationClass = self.config.operationClass;
if (operationClass && [operationClass isSubclassOfClass:[NSOperation class]] && [operationClass conformsToProtocol:@protocol(SDWebImageDownloaderOperation)]) {
// Custom operation class
} else {
if (!operationClass) {
operationClass = [SDWebImageDownloaderOperation class];
}
NSOperation<SDWebImageDownloaderOperation> *operation = [[operationClass alloc] initWithRequest:request inSession:self.session options:options context:context];

View File

@ -7,6 +7,7 @@
*/
#import "SDWebImageDownloaderConfig.h"
#import "SDWebImageDownloaderOperation.h"
static SDWebImageDownloaderConfig * _defaultDownloaderConfig;
@ -48,5 +49,12 @@ static SDWebImageDownloaderConfig * _defaultDownloaderConfig;
return config;
}
- (void)setOperationClass:(Class)operationClass {
if (operationClass) {
NSAssert([operationClass isSubclassOfClass:[NSOperation class]] && [operationClass conformsToProtocol:@protocol(SDWebImageDownloaderOperation)], @"Custom downloader operation class must subclass NSOperation and conform to `SDWebImageDownloaderOperation` protocol");
}
_operationClass = operationClass;
}
@end

View File

@ -170,7 +170,7 @@ static id<SDImageLoader> _defaultImageLoader;
id<SDImageTransformer> transformer = self.transformer;
if (context[SDWebImageContextImageTransformer]) {
transformer = context[SDWebImageContextImageTransformer];
if (![transformer conformsToProtocol:@protocol(SDImageTransformer)]) {
if ([transformer isEqual:NSNull.null]) {
transformer = nil;
}
}
@ -286,10 +286,8 @@ static id<SDImageLoader> _defaultImageLoader;
progress:(nullable SDImageLoaderProgressBlock)progressBlock
completed:(nullable SDInternalCompletionBlock)completedBlock {
// Grab the image cache to use
id<SDImageCache> imageCache;
if ([context[SDWebImageContextImageCache] conformsToProtocol:@protocol(SDImageCache)]) {
imageCache = context[SDWebImageContextImageCache];
} else {
id<SDImageCache> imageCache = context[SDWebImageContextImageCache];
if (!imageCache) {
imageCache = self.imageCache;
}
// Get the query cache type
@ -338,14 +336,11 @@ static id<SDImageLoader> _defaultImageLoader;
progress:(nullable SDImageLoaderProgressBlock)progressBlock
completed:(nullable SDInternalCompletionBlock)completedBlock {
// Grab the image cache to use, choose standalone original cache firstly
id<SDImageCache> imageCache;
if ([context[SDWebImageContextOriginalImageCache] conformsToProtocol:@protocol(SDImageCache)]) {
imageCache = context[SDWebImageContextOriginalImageCache];
} else {
id<SDImageCache> imageCache = context[SDWebImageContextOriginalImageCache];
if (!imageCache) {
// if no standalone cache available, use default cache
if ([context[SDWebImageContextImageCache] conformsToProtocol:@protocol(SDImageCache)]) {
imageCache = context[SDWebImageContextImageCache];
} else {
imageCache = context[SDWebImageContextImageCache];
if (!imageCache) {
imageCache = self.imageCache;
}
}
@ -401,10 +396,8 @@ static id<SDImageLoader> _defaultImageLoader;
}
// Grab the image loader to use
id<SDImageLoader> imageLoader;
if ([context[SDWebImageContextImageLoader] conformsToProtocol:@protocol(SDImageLoader)]) {
imageLoader = context[SDWebImageContextImageLoader];
} else {
id<SDImageLoader> imageLoader = context[SDWebImageContextImageLoader];
if (!imageLoader) {
imageLoader = self.imageLoader;
}
@ -488,7 +481,7 @@ static id<SDImageLoader> _defaultImageLoader;
finished:(BOOL)finished
completed:(nullable SDInternalCompletionBlock)completedBlock {
id<SDImageTransformer> transformer = context[SDWebImageContextImageTransformer];
if (![transformer conformsToProtocol:@protocol(SDImageTransformer)]) {
if ([transformer isEqual:NSNull.null]) {
transformer = nil;
}
// transformer check
@ -546,14 +539,11 @@ static id<SDImageLoader> _defaultImageLoader;
finished:(BOOL)finished
completed:(nullable SDInternalCompletionBlock)completedBlock {
// Grab the image cache to use, choose standalone original cache firstly
id<SDImageCache> imageCache;
if ([context[SDWebImageContextOriginalImageCache] conformsToProtocol:@protocol(SDImageCache)]) {
imageCache = context[SDWebImageContextOriginalImageCache];
} else {
id<SDImageCache> imageCache = context[SDWebImageContextOriginalImageCache];
if (!imageCache) {
// if no standalone cache available, use default cache
if ([context[SDWebImageContextImageCache] conformsToProtocol:@protocol(SDImageCache)]) {
imageCache = context[SDWebImageContextImageCache];
} else {
imageCache = context[SDWebImageContextImageCache];
if (!imageCache) {
imageCache = self.imageCache;
}
}
@ -605,10 +595,8 @@ static id<SDImageLoader> _defaultImageLoader;
finished:(BOOL)finished
completed:(nullable SDInternalCompletionBlock)completedBlock {
// Grab the image cache to use
id<SDImageCache> imageCache;
if ([context[SDWebImageContextImageCache] conformsToProtocol:@protocol(SDImageCache)]) {
imageCache = context[SDWebImageContextImageCache];
} else {
id<SDImageCache> imageCache = context[SDWebImageContextImageCache];
if (!imageCache) {
imageCache = self.imageCache;
}
BOOL waitStoreCache = SD_OPTIONS_CONTAINS(options, SDWebImageWaitStoreCache);
@ -704,10 +692,8 @@ static id<SDImageLoader> _defaultImageLoader;
error:(nonnull NSError *)error
options:(SDWebImageOptions)options
context:(nullable SDWebImageContext *)context {
id<SDImageLoader> imageLoader;
if ([context[SDWebImageContextImageLoader] conformsToProtocol:@protocol(SDImageLoader)]) {
imageLoader = context[SDWebImageContextImageLoader];
} else {
id<SDImageLoader> imageLoader = context[SDWebImageContextImageLoader];
if (!imageLoader) {
imageLoader = self.imageLoader;
}
// Check whether we should block failed url

View File

@ -60,7 +60,7 @@ typedef NSMapTable<NSString *, id<SDWebImageOperation>> SDOperationsDictionary;
operation = [operationDictionary objectForKey:key];
}
if (operation) {
if ([operation conformsToProtocol:@protocol(SDWebImageOperation)]) {
if ([operation respondsToSelector:@selector(cancel)]) {
[operation cancel];
}
@synchronized (self) {