From 9aa27b61e8573fac9259fa6e99d2feb299a109ae Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Tue, 8 Nov 2022 19:45:21 +0800 Subject: [PATCH] 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 --- SDWebImage/Core/SDAnimatedImageView.m | 2 +- SDWebImage/Core/SDImageCache.m | 8 ++-- SDWebImage/Core/SDImageCacheDefine.m | 12 +---- SDWebImage/Core/SDImageLoader.m | 22 ++------- SDWebImage/Core/SDWebImageDownloader.m | 4 +- SDWebImage/Core/SDWebImageDownloaderConfig.m | 8 ++++ SDWebImage/Core/SDWebImageManager.m | 50 +++++++------------- SDWebImage/Core/UIView+WebCacheOperation.m | 2 +- 8 files changed, 38 insertions(+), 70 deletions(-) diff --git a/SDWebImage/Core/SDAnimatedImageView.m b/SDWebImage/Core/SDAnimatedImageView.m index 35260315..db7d7675 100644 --- a/SDWebImage/Core/SDAnimatedImageView.m +++ b/SDWebImage/Core/SDAnimatedImageView.m @@ -471,7 +471,7 @@ { if ([image.class conformsToProtocol:@protocol(SDAnimatedImage)] && image.sd_isIncremental && [image respondsToSelector:@selector(animatedCoder)]) { id animatedCoder = [(id)image animatedCoder]; - if ([animatedCoder conformsToProtocol:@protocol(SDProgressiveImageCoder)]) { + if ([animatedCoder respondsToSelector:@selector(initIncrementalWithOptions:)]) { return (id)animatedCoder; } } diff --git a/SDWebImage/Core/SDImageCache.m b/SDWebImage/Core/SDImageCache.m index 3dbae354..5810996c 100644 --- a/SDWebImage/Core/SDImageCache.m +++ b/SDWebImage/Core/SDImageCache.m @@ -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)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 diff --git a/SDWebImage/Core/SDImageCacheDefine.m b/SDWebImage/Core/SDImageCacheDefine.m index 0e9ec44b..8322d76d 100644 --- a/SDWebImage/Core/SDImageCacheDefine.m +++ b/SDWebImage/Core/SDImageCacheDefine.m @@ -94,10 +94,8 @@ UIImage * _Nullable SDImageCacheDecodeImageData(NSData * _Nonnull imageData, NSS CGFloat scale = [coderOptions[SDImageCoderDecodeScaleFactor] doubleValue]; // Grab the image coder - id imageCoder; - if ([context[SDWebImageContextImageCoder] conformsToProtocol:@protocol(SDImageCoder)]) { - imageCoder = context[SDWebImageContextImageCoder]; - } else { + id 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]; diff --git a/SDWebImage/Core/SDImageLoader.m b/SDWebImage/Core/SDImageLoader.m index c8148d8b..dc547918 100644 --- a/SDWebImage/Core/SDImageLoader.m +++ b/SDWebImage/Core/SDImageLoader.m @@ -47,10 +47,8 @@ UIImage * _Nullable SDImageLoaderDecodeImageData(NSData * _Nonnull imageData, NS CGFloat scale = [coderOptions[SDImageCoderDecodeScaleFactor] doubleValue]; // Grab the image coder - id imageCoder; - if ([context[SDWebImageContextImageCoder] conformsToProtocol:@protocol(SDImageCoder)]) { - imageCoder = context[SDWebImageContextImageCoder]; - } else { + id 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 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)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]; diff --git a/SDWebImage/Core/SDWebImageDownloader.m b/SDWebImage/Core/SDWebImageDownloader.m index fbd8a5bd..8e66a8ca 100644 --- a/SDWebImage/Core/SDWebImageDownloader.m +++ b/SDWebImage/Core/SDWebImageDownloader.m @@ -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 *operation = [[operationClass alloc] initWithRequest:request inSession:self.session options:options context:context]; diff --git a/SDWebImage/Core/SDWebImageDownloaderConfig.m b/SDWebImage/Core/SDWebImageDownloaderConfig.m index 6120bd8a..6738b341 100644 --- a/SDWebImage/Core/SDWebImageDownloaderConfig.m +++ b/SDWebImage/Core/SDWebImageDownloaderConfig.m @@ -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 diff --git a/SDWebImage/Core/SDWebImageManager.m b/SDWebImage/Core/SDWebImageManager.m index 6bb7c147..a0f1f118 100644 --- a/SDWebImage/Core/SDWebImageManager.m +++ b/SDWebImage/Core/SDWebImageManager.m @@ -170,7 +170,7 @@ static id _defaultImageLoader; id 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 _defaultImageLoader; progress:(nullable SDImageLoaderProgressBlock)progressBlock completed:(nullable SDInternalCompletionBlock)completedBlock { // Grab the image cache to use - id imageCache; - if ([context[SDWebImageContextImageCache] conformsToProtocol:@protocol(SDImageCache)]) { - imageCache = context[SDWebImageContextImageCache]; - } else { + id imageCache = context[SDWebImageContextImageCache]; + if (!imageCache) { imageCache = self.imageCache; } // Get the query cache type @@ -338,14 +336,11 @@ static id _defaultImageLoader; progress:(nullable SDImageLoaderProgressBlock)progressBlock completed:(nullable SDInternalCompletionBlock)completedBlock { // Grab the image cache to use, choose standalone original cache firstly - id imageCache; - if ([context[SDWebImageContextOriginalImageCache] conformsToProtocol:@protocol(SDImageCache)]) { - imageCache = context[SDWebImageContextOriginalImageCache]; - } else { + id 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 _defaultImageLoader; } // Grab the image loader to use - id imageLoader; - if ([context[SDWebImageContextImageLoader] conformsToProtocol:@protocol(SDImageLoader)]) { - imageLoader = context[SDWebImageContextImageLoader]; - } else { + id imageLoader = context[SDWebImageContextImageLoader]; + if (!imageLoader) { imageLoader = self.imageLoader; } @@ -488,7 +481,7 @@ static id _defaultImageLoader; finished:(BOOL)finished completed:(nullable SDInternalCompletionBlock)completedBlock { id transformer = context[SDWebImageContextImageTransformer]; - if (![transformer conformsToProtocol:@protocol(SDImageTransformer)]) { + if ([transformer isEqual:NSNull.null]) { transformer = nil; } // transformer check @@ -546,14 +539,11 @@ static id _defaultImageLoader; finished:(BOOL)finished completed:(nullable SDInternalCompletionBlock)completedBlock { // Grab the image cache to use, choose standalone original cache firstly - id imageCache; - if ([context[SDWebImageContextOriginalImageCache] conformsToProtocol:@protocol(SDImageCache)]) { - imageCache = context[SDWebImageContextOriginalImageCache]; - } else { + id 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 _defaultImageLoader; finished:(BOOL)finished completed:(nullable SDInternalCompletionBlock)completedBlock { // Grab the image cache to use - id imageCache; - if ([context[SDWebImageContextImageCache] conformsToProtocol:@protocol(SDImageCache)]) { - imageCache = context[SDWebImageContextImageCache]; - } else { + id imageCache = context[SDWebImageContextImageCache]; + if (!imageCache) { imageCache = self.imageCache; } BOOL waitStoreCache = SD_OPTIONS_CONTAINS(options, SDWebImageWaitStoreCache); @@ -704,10 +692,8 @@ static id _defaultImageLoader; error:(nonnull NSError *)error options:(SDWebImageOptions)options context:(nullable SDWebImageContext *)context { - id imageLoader; - if ([context[SDWebImageContextImageLoader] conformsToProtocol:@protocol(SDImageLoader)]) { - imageLoader = context[SDWebImageContextImageLoader]; - } else { + id imageLoader = context[SDWebImageContextImageLoader]; + if (!imageLoader) { imageLoader = self.imageLoader; } // Check whether we should block failed url diff --git a/SDWebImage/Core/UIView+WebCacheOperation.m b/SDWebImage/Core/UIView+WebCacheOperation.m index 6fe23e48..e884c4cf 100644 --- a/SDWebImage/Core/UIView+WebCacheOperation.m +++ b/SDWebImage/Core/UIView+WebCacheOperation.m @@ -60,7 +60,7 @@ typedef NSMapTable> SDOperationsDictionary; operation = [operationDictionary objectForKey:key]; } if (operation) { - if ([operation conformsToProtocol:@protocol(SDWebImageOperation)]) { + if ([operation respondsToSelector:@selector(cancel)]) { [operation cancel]; } @synchronized (self) {