diff --git a/SDWebImage/SDWebImageDownloader.h b/SDWebImage/SDWebImageDownloader.h index b5911aff..906eaa7f 100644 --- a/SDWebImage/SDWebImageDownloader.h +++ b/SDWebImage/SDWebImageDownloader.h @@ -197,12 +197,13 @@ typedef SDHTTPHeadersDictionary * _Nullable (^SDWebImageDownloaderHeadersFilterB - (nullable NSString *)valueForHTTPHeaderField:(nullable NSString *)field; /** - * Sets a subclass of `SDWebImageDownloaderOperation` as the default - * `NSOperation` to be used each time SDWebImage constructs a request + * Sets a subclass of `NSOperation` and conforms to `SDWebImageDownloaderOperationInterface`. + * Default is `SDWebImageDownloaderOperation`. + * Can be used each time SDWebImage constructs a request * operation to download an image. * - * @param operationClass The subclass of `SDWebImageDownloaderOperation` to set - * as default. Passing `nil` will revert to `SDWebImageDownloaderOperation`. + * @param operationClass The subclass of `NSOperation` and conforms to `SDWebImageDownloaderOperationInterface`. + * Default is `SDWebImageDownloaderOperation`, Passing `nil` will revert to `SDWebImageDownloaderOperation`. */ - (void)setOperationClass:(nullable Class)operationClass; diff --git a/SDWebImage/SDWebImageDownloader.m b/SDWebImage/SDWebImageDownloader.m index 76291a17..66c17677 100644 --- a/SDWebImage/SDWebImageDownloader.m +++ b/SDWebImage/SDWebImageDownloader.m @@ -37,7 +37,7 @@ @property (strong, nonatomic, nonnull) NSOperationQueue *downloadQueue; @property (weak, nonatomic, nullable) NSOperation *lastAddedOperation; @property (assign, nonatomic, nullable) Class operationClass; -@property (strong, nonatomic, nonnull) NSMutableDictionary *URLOperations; +@property (strong, nonatomic, nonnull) NSMutableDictionary *> *URLOperations; @property (strong, nonatomic, nullable) SDHTTPHeadersMutableDictionary *HTTPHeaders; @property (strong, nonatomic, nonnull) dispatch_semaphore_t operationsLock; // a lock to keep the access to `URLOperations` thread-safe @property (strong, nonatomic, nonnull) dispatch_semaphore_t headersLock; // a lock to keep the access to `HTTPHeaders` thread-safe @@ -199,7 +199,7 @@ completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock { __weak SDWebImageDownloader *wself = self; - return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^SDWebImageDownloaderOperation *{ + return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^NSOperation *{ __strong __typeof (wself) sself = wself; NSTimeInterval timeoutInterval = sself.downloadTimeout; if (timeoutInterval == 0.0) { @@ -220,7 +220,7 @@ else { request.allHTTPHeaderFields = [sself allHTTPHeaderFields]; } - SDWebImageDownloaderOperation *operation = [[sself.operationClass alloc] initWithRequest:request inSession:sself.session options:options]; + NSOperation *operation = [[sself.operationClass alloc] initWithRequest:request inSession:sself.session options:options]; operation.shouldDecompressImages = sself.shouldDecompressImages; if (sself.urlCredential) { @@ -251,7 +251,7 @@ return; } LOCK(self.operationsLock); - SDWebImageDownloaderOperation *operation = [self.URLOperations objectForKey:url]; + NSOperation *operation = [self.URLOperations objectForKey:url]; if (operation) { BOOL canceled = [operation cancel:token.downloadOperationCancelToken]; if (canceled) { @@ -264,7 +264,7 @@ - (nullable SDWebImageDownloadToken *)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock forURL:(nullable NSURL *)url - createCallback:(SDWebImageDownloaderOperation *(^)(void))createCallback { + createCallback:(NSOperation *(^)(void))createCallback { // 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. if (url == nil) { if (completedBlock != nil) { @@ -274,7 +274,7 @@ } LOCK(self.operationsLock); - SDWebImageDownloaderOperation *operation = [self.URLOperations objectForKey:url]; + NSOperation *operation = [self.URLOperations objectForKey:url]; // There is a case that the operation may be marked as finished, but not been removed from `self.URLOperations`. if (!operation || operation.isFinished) { operation = createCallback(); @@ -315,12 +315,14 @@ #pragma mark Helper methods -- (SDWebImageDownloaderOperation *)operationWithTask:(NSURLSessionTask *)task { - SDWebImageDownloaderOperation *returnOperation = nil; - for (SDWebImageDownloaderOperation *operation in self.downloadQueue.operations) { - if (operation.dataTask.taskIdentifier == task.taskIdentifier) { - returnOperation = operation; - break; +- (NSOperation *)operationWithTask:(NSURLSessionTask *)task { + NSOperation *returnOperation = nil; + for (NSOperation *operation in self.downloadQueue.operations) { + if ([operation respondsToSelector:@selector(dataTask)]) { + if (operation.dataTask.taskIdentifier == task.taskIdentifier) { + returnOperation = operation; + break; + } } } return returnOperation; @@ -334,7 +336,7 @@ didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { // Identify the operation that runs this task and pass it the delegate method - SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:dataTask]; + NSOperation *dataOperation = [self operationWithTask:dataTask]; if ([dataOperation respondsToSelector:@selector(URLSession:dataTask:didReceiveResponse:completionHandler:)]) { [dataOperation URLSession:session dataTask:dataTask didReceiveResponse:response completionHandler:completionHandler]; } else { @@ -347,7 +349,7 @@ didReceiveResponse:(NSURLResponse *)response - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { // Identify the operation that runs this task and pass it the delegate method - SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:dataTask]; + NSOperation *dataOperation = [self operationWithTask:dataTask]; if ([dataOperation respondsToSelector:@selector(URLSession:dataTask:didReceiveData:)]) { [dataOperation URLSession:session dataTask:dataTask didReceiveData:data]; } @@ -359,7 +361,7 @@ didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler { // Identify the operation that runs this task and pass it the delegate method - SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:dataTask]; + NSOperation *dataOperation = [self operationWithTask:dataTask]; if ([dataOperation respondsToSelector:@selector(URLSession:dataTask:willCacheResponse:completionHandler:)]) { [dataOperation URLSession:session dataTask:dataTask willCacheResponse:proposedResponse completionHandler:completionHandler]; } else { @@ -374,7 +376,7 @@ didReceiveResponse:(NSURLResponse *)response - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { // Identify the operation that runs this task and pass it the delegate method - SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:task]; + NSOperation *dataOperation = [self operationWithTask:task]; if ([dataOperation respondsToSelector:@selector(URLSession:task:didCompleteWithError:)]) { [dataOperation URLSession:session task:task didCompleteWithError:error]; } @@ -383,7 +385,7 @@ didReceiveResponse:(NSURLResponse *)response - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler { // Identify the operation that runs this task and pass it the delegate method - SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:task]; + NSOperation *dataOperation = [self operationWithTask:task]; if ([dataOperation respondsToSelector:@selector(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:)]) { [dataOperation URLSession:session task:task willPerformHTTPRedirection:response newRequest:request completionHandler:completionHandler]; } else { @@ -396,7 +398,7 @@ didReceiveResponse:(NSURLResponse *)response - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { // Identify the operation that runs this task and pass it the delegate method - SDWebImageDownloaderOperation *dataOperation = [self operationWithTask:task]; + NSOperation *dataOperation = [self operationWithTask:task]; if ([dataOperation respondsToSelector:@selector(URLSession:task:didReceiveChallenge:completionHandler:)]) { [dataOperation URLSession:session task:task didReceiveChallenge:challenge completionHandler:completionHandler]; } else { diff --git a/SDWebImage/SDWebImageDownloaderOperation.h b/SDWebImage/SDWebImageDownloaderOperation.h index d0c58153..390e9078 100644 --- a/SDWebImage/SDWebImageDownloaderOperation.h +++ b/SDWebImage/SDWebImageDownloaderOperation.h @@ -21,8 +21,8 @@ FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageDownloadFinishNotification Describes a downloader operation. If one wants to use a custom downloader op, it needs to inherit from `NSOperation` and conform to this protocol For the description about these methods, see `SDWebImageDownloaderOperation` */ -@protocol SDWebImageDownloaderOperationInterface - +@protocol SDWebImageDownloaderOperationInterface +@required - (nonnull instancetype)initWithRequest:(nullable NSURLRequest *)request inSession:(nullable NSURLSession *)session options:(SDWebImageDownloaderOptions)options; @@ -38,6 +38,9 @@ FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageDownloadFinishNotification - (BOOL)cancel:(nullable id)token; +@optional +- (nullable NSURLSessionTask *)dataTask; + @end diff --git a/SDWebImage/UIView+WebCache.m b/SDWebImage/UIView+WebCache.m index 953415b3..88def759 100644 --- a/SDWebImage/UIView+WebCache.m +++ b/SDWebImage/UIView+WebCache.m @@ -82,10 +82,8 @@ static char TAG_ACTIVITY_SHOW; self.sd_imageProgress.totalUnitCount = 0; self.sd_imageProgress.completedUnitCount = 0; - SDWebImageManager *manager; - if ([context valueForKey:SDWebImageExternalCustomManagerKey]) { - manager = (SDWebImageManager *)[context valueForKey:SDWebImageExternalCustomManagerKey]; - } else { + SDWebImageManager *manager = [context objectForKey:SDWebImageExternalCustomManagerKey]; + if (!manager) { manager = [SDWebImageManager sharedManager]; }