Fix the iOS 12 crash because the underlyingQueue is nil

Use NSOperation dependency to solve this issue
This commit is contained in:
DreamPiggy 2022-11-10 19:55:18 +08:00
parent b6aa428b7d
commit d96ea392d1
3 changed files with 21 additions and 21 deletions

View File

@ -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

View File

@ -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
*/

View File

@ -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"}]];