Merge pull request #3142 from dreampiggy/fix_race_condition_cancel_callback

Fix the race condition when user cancel the network loading will not trigger the completion block
This commit is contained in:
DreamPiggy 2020-12-25 16:25:34 +08:00 committed by GitHub
commit ef9c1d6480
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 12 deletions

View File

@ -232,22 +232,25 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
- (void)cancelInternal {
if (self.isFinished) return;
[super cancel];
__block typeof(self) strongSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:strongSelf];
});
// As we cancelled the task, its callback won't be called and thus won't
// maintain the isFinished and isExecuting flags.
if (self.isExecuting) self.executing = NO;
if (!self.isFinished) self.finished = YES;
if (self.dataTask) {
// Cancel the URLSession, `URLSession:task:didCompleteWithError:` delegate callback will be ignored
[self.dataTask cancel];
__block typeof(self) strongSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:strongSelf];
});
// As we cancelled the task, its callback won't be called and thus won't
// maintain the isFinished and isExecuting flags.
if (self.isExecuting) self.executing = NO;
if (!self.isFinished) self.finished = YES;
} else {
// Operation cancelled by user during sending the request
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorCancelled userInfo:@{NSLocalizedDescriptionKey : @"Operation cancelled by user during sending the request"}]];
self.dataTask = nil;
}
// Operation cancelled by user during sending the request
[self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorCancelled userInfo:@{NSLocalizedDescriptionKey : @"Operation cancelled by user during sending the request"}]];
[self reset];
}

View File

@ -174,6 +174,7 @@
SDWebImageDownloadToken *token = [[SDWebImageDownloader sharedDownloader]
downloadImageWithURL:imageURL options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished) {
expect(error).notTo.beNil();
expect(error.domain).equal(SDWebImageErrorDomain);
expect(error.code).equal(SDWebImageErrorCancelled);
}];
expect([SDWebImageDownloader sharedDownloader].currentDownloadCount).to.equal(1);
@ -685,6 +686,27 @@
}];
}
- (void)test27DownloadShouldCallbackWhenURLSessionRunning {
XCTestExpectation *expectation = [self expectationWithDescription:@"Downloader should callback when URLSessionTask running"];
NSURL *url = [NSURL URLWithString: @"https://raw.githubusercontent.com/SDWebImage/SDWebImage/master/SDWebImage_logo.png"];
NSString *key = [SDWebImageManager.sharedManager cacheKeyForURL:url];
[SDImageCache.sharedImageCache removeImageForKey:key withCompletion:^{
SDWebImageCombinedOperation *operation = [SDWebImageManager.sharedManager loadImageWithURL:url options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
expect(error.domain).equal(SDWebImageErrorDomain);
expect(error.code).equal(SDWebImageErrorCancelled);
[expectation fulfill];
}];
dispatch_async(dispatch_get_main_queue(), ^{
[operation cancel];
});
}];
[self waitForExpectationsWithCommonTimeout];
}
#pragma mark - SDWebImageLoader
- (void)test30CustomImageLoaderWorks {
XCTestExpectation *expectation = [self expectationWithDescription:@"Custom image not works"];