Authored by Bogdan Poplauschi

Update to <Fix multiple requests for same image and then canceling one> feature …

…- exposed the SDWebImageDownloadToken class
@@ -73,6 +73,17 @@ typedef void(^SDWebImageDownloaderCompletedBlock)(UIImage *image, NSData *data, @@ -73,6 +73,17 @@ typedef void(^SDWebImageDownloaderCompletedBlock)(UIImage *image, NSData *data,
73 typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDictionary *headers); 73 typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDictionary *headers);
74 74
75 /** 75 /**
  76 + * A token associated with each download. Can be used to cancel a download
  77 + */
  78 +@interface SDWebImageDownloadToken : NSObject
  79 +
  80 +@property (nonatomic, strong) NSURL *url;
  81 +@property (nonatomic, strong) id downloadOperationCancelToken;
  82 +
  83 +@end
  84 +
  85 +
  86 +/**
76 * Asynchronous downloader dedicated and optimized for image loading. 87 * Asynchronous downloader dedicated and optimized for image loading.
77 */ 88 */
78 @interface SDWebImageDownloader : NSObject 89 @interface SDWebImageDownloader : NSObject
@@ -176,19 +187,19 @@ typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDi @@ -176,19 +187,19 @@ typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDi
176 * before to be called a last time with the full image and finished argument 187 * before to be called a last time with the full image and finished argument
177 * set to YES. In case of error, the finished argument is always YES. 188 * set to YES. In case of error, the finished argument is always YES.
178 * 189 *
179 - * @return A token that can be passed to -cancel: to cancel this operation 190 + * @return A token (SDWebImageDownloadToken) that can be passed to -cancel: to cancel this operation
180 */ 191 */
181 -- (id)downloadImageWithURL:(NSURL *)url  
182 - options:(SDWebImageDownloaderOptions)options  
183 - progress:(SDWebImageDownloaderProgressBlock)progressBlock  
184 - completed:(SDWebImageDownloaderCompletedBlock)completedBlock; 192 +- (SDWebImageDownloadToken *)downloadImageWithURL:(NSURL *)url
  193 + options:(SDWebImageDownloaderOptions)options
  194 + progress:(SDWebImageDownloaderProgressBlock)progressBlock
  195 + completed:(SDWebImageDownloaderCompletedBlock)completedBlock;
185 196
186 /** 197 /**
187 * Cancels a download that was previously queued using -downloadImageWithURL:options:progress:completed: 198 * Cancels a download that was previously queued using -downloadImageWithURL:options:progress:completed:
188 * 199 *
189 * @param token The token received from -downloadImageWithURL:options:progress:completed: that should be canceled. 200 * @param token The token received from -downloadImageWithURL:options:progress:completed: that should be canceled.
190 */ 201 */
191 -- (void)cancel:(id)token; 202 +- (void)cancel:(SDWebImageDownloadToken *)token;
192 203
193 /** 204 /**
194 * Sets the download queue suspension state 205 * Sets the download queue suspension state
@@ -10,15 +10,9 @@ @@ -10,15 +10,9 @@
10 #import "SDWebImageDownloaderOperation.h" 10 #import "SDWebImageDownloaderOperation.h"
11 #import <ImageIO/ImageIO.h> 11 #import <ImageIO/ImageIO.h>
12 12
13 -@interface _SDWebImageDownloaderToken : NSObject  
14 -  
15 -@property (nonatomic, strong) NSURL *url;  
16 -@property (nonatomic, strong) id downloadOperationCancelToken;  
17 - 13 +@implementation SDWebImageDownloadToken
18 @end 14 @end
19 15
20 -@implementation _SDWebImageDownloaderToken  
21 -@end  
22 16
23 @interface SDWebImageDownloader () 17 @interface SDWebImageDownloader ()
24 18
@@ -119,7 +113,10 @@ @@ -119,7 +113,10 @@
119 _operationClass = operationClass ?: [SDWebImageDownloaderOperation class]; 113 _operationClass = operationClass ?: [SDWebImageDownloaderOperation class];
120 } 114 }
121 115
122 -- (id)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageDownloaderCompletedBlock)completedBlock { 116 +- (SDWebImageDownloadToken *)downloadImageWithURL:(NSURL *)url
  117 + options:(SDWebImageDownloaderOptions)options
  118 + progress:(SDWebImageDownloaderProgressBlock)progressBlock
  119 + completed:(SDWebImageDownloaderCompletedBlock)completedBlock {
123 __weak SDWebImageDownloader *wself = self; 120 __weak SDWebImageDownloader *wself = self;
124 121
125 return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^SDWebImageDownloaderOperation *{ 122 return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^SDWebImageDownloaderOperation *{
@@ -164,22 +161,20 @@ @@ -164,22 +161,20 @@
164 }]; 161 }];
165 } 162 }
166 163
167 -- (void)cancel:(id)token {  
168 - if (![token isKindOfClass:[_SDWebImageDownloaderToken class]]) {  
169 - return;  
170 - }  
171 - 164 +- (void)cancel:(SDWebImageDownloadToken *)token {
172 dispatch_barrier_async(self.barrierQueue, ^{ 165 dispatch_barrier_async(self.barrierQueue, ^{
173 - _SDWebImageDownloaderToken *typedToken = (_SDWebImageDownloaderToken *)token;  
174 - SDWebImageDownloaderOperation *operation = self.URLOperations[typedToken.url];  
175 - BOOL canceled = [operation cancel:typedToken.downloadOperationCancelToken]; 166 + SDWebImageDownloaderOperation *operation = self.URLOperations[token.url];
  167 + BOOL canceled = [operation cancel:token.downloadOperationCancelToken];
176 if (canceled) { 168 if (canceled) {
177 - [self.URLOperations removeObjectForKey:typedToken.url]; 169 + [self.URLOperations removeObjectForKey:token.url];
178 } 170 }
179 }); 171 });
180 } 172 }
181 173
182 -- (id)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(NSURL *)url createCallback:(SDWebImageDownloaderOperation *(^)())createCallback { 174 +- (SDWebImageDownloadToken *)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock
  175 + completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock
  176 + forURL:(NSURL *)url
  177 + createCallback:(SDWebImageDownloaderOperation *(^)())createCallback {
183 // The URL will be used as the key to the callbacks dictionary so it cannot be nil. If it is nil immediately call the completed block with no image or data. 178 // The URL will be used as the key to the callbacks dictionary so it cannot be nil. If it is nil immediately call the completed block with no image or data.
184 if (url == nil) { 179 if (url == nil) {
185 if (completedBlock != nil) { 180 if (completedBlock != nil) {
@@ -188,7 +183,7 @@ @@ -188,7 +183,7 @@
188 return nil; 183 return nil;
189 } 184 }
190 185
191 - __block _SDWebImageDownloaderToken *token = nil; 186 + __block SDWebImageDownloadToken *token = nil;
192 187
193 dispatch_barrier_sync(self.barrierQueue, ^{ 188 dispatch_barrier_sync(self.barrierQueue, ^{
194 SDWebImageDownloaderOperation *operation = self.URLOperations[url]; 189 SDWebImageDownloaderOperation *operation = self.URLOperations[url];
@@ -207,7 +202,7 @@ @@ -207,7 +202,7 @@
207 } 202 }
208 id downloadOperationCancelToken = [operation addHandlersForProgress:progressBlock completed:completedBlock]; 203 id downloadOperationCancelToken = [operation addHandlersForProgress:progressBlock completed:completedBlock];
209 204
210 - token = [_SDWebImageDownloaderToken new]; 205 + token = [SDWebImageDownloadToken new];
211 token.url = url; 206 token.url = url;
212 token.downloadOperationCancelToken = downloadOperationCancelToken; 207 token.downloadOperationCancelToken = downloadOperationCancelToken;
213 }); 208 });