diff --git a/SDWebImage/Core/SDAnimatedImagePlayer.m b/SDWebImage/Core/SDAnimatedImagePlayer.m index a03f78b1..31cbcb67 100644 --- a/SDWebImage/Core/SDAnimatedImagePlayer.m +++ b/SDWebImage/Core/SDAnimatedImagePlayer.m @@ -70,7 +70,7 @@ - (void)didReceiveMemoryWarning:(NSNotification *)notification { [_fetchQueue cancelAllOperations]; - [_fetchQueue addOperationWithBlock:^{ + NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ NSNumber *currentFrameIndex = @(self.currentFrameIndex); SD_LOCK(self->_lock); NSArray *keys = self.frameBuffer.allKeys; @@ -82,6 +82,7 @@ } SD_UNLOCK(self->_lock); }]; + [_fetchQueue addOperation:operation]; } #pragma mark - Private diff --git a/SDWebImage/Core/SDImageCoderHelper.h b/SDWebImage/Core/SDImageCoderHelper.h index 28e12401..8502b391 100644 --- a/SDWebImage/Core/SDImageCoderHelper.h +++ b/SDWebImage/Core/SDImageCoderHelper.h @@ -104,7 +104,7 @@ typedef NS_ENUM(NSUInteger, SDImageCoderDecodeSolution) { + (CGSize)scaledSizeWithImageSize:(CGSize)imageSize scaleSize:(CGSize)scaleSize preserveAspectRatio:(BOOL)preserveAspectRatio shouldScaleUp:(BOOL)shouldScaleUp; /** - Return the decoded image by the provided image. This one unlike `CGImageCreateDecoded:`, will not decode the image which contains alpha channel or animated image + Return the decoded image by the provided image. This one unlike `CGImageCreateDecoded:`, will not decode the image which contains alpha channel or animated image. On iOS 15+, this may use `UIImage.preparingForDisplay()` to use CMPhoto for better performance than the old solution. @param image The image to be decoded @return The decoded image */ diff --git a/SDWebImage/Core/SDWebImageDownloaderOperation.m b/SDWebImage/Core/SDWebImageDownloaderOperation.m index 2729dc50..837883e2 100644 --- a/SDWebImage/Core/SDWebImageDownloaderOperation.m +++ b/SDWebImage/Core/SDWebImageDownloaderOperation.m @@ -472,18 +472,22 @@ didReceiveResponse:(NSURLResponse *)response if (self.coderQueue.operationCount == 0) { // NSOperation have autoreleasepool, don't need to create extra one @weakify(self); - [self.coderQueue addOperationWithBlock:^{ + NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ @strongify(self); if (!self) { return; } UIImage *image = SDImageLoaderDecodeProgressiveImageData(imageData, self.request.URL, NO, self, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context); + if (self.isFinished) { + return; + } if (image) { // We do not keep the progressive decoding image even when `finished`=YES. Because they are for view rendering but not take full function from downloader options. And some coders implementation may not keep consistent between progressive decoding and normal decoding. [self callCompletionBlocksWithImage:image imageData:nil error:nil finished:NO]; } }]; + [self.coderQueue addOperation:operation]; } } @@ -561,8 +565,16 @@ didReceiveResponse:(NSURLResponse *)response // decode the image in coder queue, cancel all previous decoding process [self.coderQueue cancelAllOperations]; @weakify(self); + // call done after all different variant completed block was dispatched + NSOperation *doneOperation = [NSBlockOperation blockOperationWithBlock:^{ + @strongify(self); + if (!self) { + return; + } + [self done]; + }]; for (SDWebImageDownloaderOperationToken *token in tokens) { - [self.coderQueue addOperationWithBlock:^{ + NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ @strongify(self); if (!self) { return; @@ -601,24 +613,11 @@ didReceiveResponse:(NSURLResponse *)response [self callCompletionBlockWithToken:token image:image imageData:imageData error:nil finished:YES]; } }]; + [doneOperation addDependency:operation]; + [self.coderQueue addOperation:operation]; } - if (@available(iOS 13.0, tvOS 13.0, macOS 10.15, watchOS 6.0, *)) { - [self.coderQueue addBarrierBlock:^{ - @strongify(self); - if (!self) { - return; - } - [self done]; - }]; - } else { - dispatch_barrier_async(self.coderQueue.underlyingQueue, ^{ - @strongify(self); - if (!self) { - return; - } - [self done]; - }); - } + // call [self done] after all completed block was dispatched + [self.coderQueue addOperation:doneOperation]; } } else { [self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}]];