From a46f6149e502862ef8b8b02a39a8df118dea3f3c Mon Sep 17 00:00:00 2001 From: robertmryan Date: Wed, 11 Jun 2014 02:14:40 -0400 Subject: [PATCH 1/2] Resolve race condition. While exceedingly unlikely, the old construct introduced potential race condition where it checked wself first, and assigned sself second. This now assigns sself first, and then checks that, which is the correct pattern, already used elsewhere in SDWebImage. --- SDWebImage/SDWebImageDownloader.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SDWebImage/SDWebImageDownloader.m b/SDWebImage/SDWebImageDownloader.m index 09ceb4f..251bc51 100644 --- a/SDWebImage/SDWebImageDownloader.m +++ b/SDWebImage/SDWebImageDownloader.m @@ -127,8 +127,8 @@ static NSString *const kCompletedCallbackKey = @"completed"; operation = [[SDWebImageDownloaderOperation alloc] initWithRequest:request options:options progress:^(NSInteger receivedSize, NSInteger expectedSize) { - if (!wself) return; SDWebImageDownloader *sself = wself; + if (!sself) return; NSArray *callbacksForURL = [sself callbacksForURL:url]; for (NSDictionary *callbacks in callbacksForURL) { SDWebImageDownloaderProgressBlock callback = callbacks[kProgressCallbackKey]; @@ -136,8 +136,8 @@ static NSString *const kCompletedCallbackKey = @"completed"; } } completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) { - if (!wself) return; SDWebImageDownloader *sself = wself; + if (!sself) return; NSArray *callbacksForURL = [sself callbacksForURL:url]; if (finished) { [sself removeCallbacksForURL:url]; @@ -148,8 +148,8 @@ static NSString *const kCompletedCallbackKey = @"completed"; } } cancelled:^{ - if (!wself) return; SDWebImageDownloader *sself = wself; + if (!sself) return; [sself removeCallbacksForURL:url]; }]; From f63a45add6a4c365fdfad68ff2bef5c5bd5d15a7 Mon Sep 17 00:00:00 2001 From: robertmryan Date: Wed, 11 Jun 2014 02:36:47 -0400 Subject: [PATCH 2/2] Adjusted completion logic in prefetcher, as the old implementation would finish prematurely if any requests were skipped. Also adjusted documentation in headers to make it clear that the `finishedCount` includes both successful and unsuccessful requests. --- SDWebImage/SDWebImagePrefetcher.h | 8 ++++---- SDWebImage/SDWebImagePrefetcher.m | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SDWebImage/SDWebImagePrefetcher.h b/SDWebImage/SDWebImagePrefetcher.h index 991602a..781635b 100644 --- a/SDWebImage/SDWebImagePrefetcher.h +++ b/SDWebImage/SDWebImagePrefetcher.h @@ -20,15 +20,15 @@ * * @param imagePrefetcher The current image prefetcher * @param imageURL The image url that was prefetched - * @param finishedCount The total number of images that were prefetched - * @param totalCount The total number of images that need to be prefetched + * @param finishedCount The total number of images that were prefetched (successful or not) + * @param totalCount The total number of images that were to be prefetched */ - (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didPrefetchURL:(NSURL *)imageURL finishedCount:(NSUInteger)finishedCount totalCount:(NSUInteger)totalCount; /** * Called when all images are prefetched. * @param imagePrefetcher The current image prefetcher - * @param totalCount The total number of images that need to be prefetched + * @param totalCount The total number of images that were prefetched (whether successful or not) * @param skippedCount The total number of images that were skipped */ - (void)imagePrefetcher:(SDWebImagePrefetcher *)imagePrefetcher didFinishWithTotalCount:(NSUInteger)totalCount skippedCount:(NSUInteger)skippedCount; @@ -73,7 +73,7 @@ * and skips images for failed downloads and proceed to the next image in the list * * @param urls list of URLs to prefetch - * @param progressBlock block to be called when progress updates + * @param progressBlock block to be called when progress updates; first parameter is the number of completed (successful or not) requests, second parameter is the total number of images originally requested to be prefetched * @param completionBlock block to be called when prefetching is completed */ - (void)prefetchURLs:(NSArray *)urls progress:(void (^)(NSUInteger, NSUInteger))progressBlock completed:(void (^)(NSUInteger, NSUInteger))completionBlock; diff --git a/SDWebImage/SDWebImagePrefetcher.m b/SDWebImage/SDWebImagePrefetcher.m index 74a3bc1..8c4bc2f 100644 --- a/SDWebImage/SDWebImagePrefetcher.m +++ b/SDWebImage/SDWebImagePrefetcher.m @@ -88,7 +88,7 @@ [self startPrefetchingAtIndex:self.requestedCount]; }); } - else if (self.finishedCount + self.skippedCount == self.requestedCount) { + else if (self.finishedCount == self.requestedCount) { [self reportStatus]; if (self.completionBlock) { self.completionBlock(self.finishedCount, self.skippedCount);