Authored by DreamPiggy

Add a delegate method to control the custom logic when blocking the failed url

@@ -142,6 +142,16 @@ typedef NSString * _Nullable (^SDWebImageCacheKeyFilterBlock)(NSURL * _Nullable @@ -142,6 +142,16 @@ typedef NSString * _Nullable (^SDWebImageCacheKeyFilterBlock)(NSURL * _Nullable
142 - (BOOL)imageManager:(nonnull SDWebImageManager *)imageManager shouldDownloadImageForURL:(nullable NSURL *)imageURL; 142 - (BOOL)imageManager:(nonnull SDWebImageManager *)imageManager shouldDownloadImageForURL:(nullable NSURL *)imageURL;
143 143
144 /** 144 /**
  145 + * Controls the complicated logic to mark as failed URLs when download error occur.
  146 + * If the delegate implement this method, we will not use the built-in way to mark URL as failed based on error code;
  147 + @param imageManager The current `SDWebImageManager`
  148 + @param imageURL The url of the image
  149 + @param error The download error for the url
  150 + @return Whether to block this url or not. Return YES to mark this URL as failed.
  151 + */
  152 +- (BOOL)imageManager:(nonnull SDWebImageManager *)imageManager shouldBlockFailedURL:(nonnull NSURL *)imageURL withError:(nonnull NSError *)error;
  153 +
  154 +/**
145 * Allows to transform the image immediately after it has been downloaded and just before to cache it on disk and memory. 155 * Allows to transform the image immediately after it has been downloaded and just before to cache it on disk and memory.
146 * NOTE: This method is called from a global queue in order to not to block the main thread. 156 * NOTE: This method is called from a global queue in order to not to block the main thread.
147 * 157 *
@@ -196,15 +196,22 @@ @@ -196,15 +196,22 @@
196 // if we would call the completedBlock, there could be a race condition between this block and another completedBlock for the same object, so if this one is called second, we will overwrite the new data 196 // if we would call the completedBlock, there could be a race condition between this block and another completedBlock for the same object, so if this one is called second, we will overwrite the new data
197 } else if (error) { 197 } else if (error) {
198 [self callCompletionBlockForOperation:strongSubOperation completion:completedBlock error:error url:url]; 198 [self callCompletionBlockForOperation:strongSubOperation completion:completedBlock error:error url:url];
199 -  
200 - if ( error.code != NSURLErrorNotConnectedToInternet  
201 - && error.code != NSURLErrorCancelled  
202 - && error.code != NSURLErrorTimedOut  
203 - && error.code != NSURLErrorInternationalRoamingOff  
204 - && error.code != NSURLErrorDataNotAllowed  
205 - && error.code != NSURLErrorCannotFindHost  
206 - && error.code != NSURLErrorCannotConnectToHost  
207 - && error.code != NSURLErrorNetworkConnectionLost) { 199 + BOOL shouldBlockFailedURL;
  200 + // Check whether we should block failed url
  201 + if ([self.delegate respondsToSelector:@selector(imageManager:shouldBlockFailedURL:withError:)]) {
  202 + shouldBlockFailedURL = [self.delegate imageManager:self shouldBlockFailedURL:url withError:error];
  203 + } else {
  204 + shouldBlockFailedURL = ( error.code != NSURLErrorNotConnectedToInternet
  205 + && error.code != NSURLErrorCancelled
  206 + && error.code != NSURLErrorTimedOut
  207 + && error.code != NSURLErrorInternationalRoamingOff
  208 + && error.code != NSURLErrorDataNotAllowed
  209 + && error.code != NSURLErrorCannotFindHost
  210 + && error.code != NSURLErrorCannotConnectToHost
  211 + && error.code != NSURLErrorNetworkConnectionLost);
  212 + }
  213 +
  214 + if (shouldBlockFailedURL) {
208 @synchronized (self.failedURLs) { 215 @synchronized (self.failedURLs) {
209 [self.failedURLs addObject:url]; 216 [self.failedURLs addObject:url];
210 } 217 }