Fix the race condition when user cancel the network loading will not trigger the completion block.

Now we do not relay on URLSession delegate timing, directly callback when cancelled.
This commit is contained in:
DreamPiggy 2020-12-24 13:04:47 +08:00
parent 7a17674f7e
commit 9a010de0e8
1 changed files with 14 additions and 9 deletions

View File

@ -232,18 +232,23 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
- (void)cancelInternal { - (void)cancelInternal {
if (self.isFinished) return; if (self.isFinished) return;
[super cancel]; [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) { if (self.dataTask) {
[self.dataTask cancel]; [self.dataTask cancel];
__block typeof(self) strongSelf = self; self.dataTask = nil;
dispatch_async(dispatch_get_main_queue(), ^{ // Provide the same userInfo as URLSession if network is cancelled
[[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:strongSelf]; // Don't relay on `URLSession:task:didCompleteWithError:` delegate callback because it may delay
}); [self callCompletionBlocksWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:@{NSLocalizedDescriptionKey: @"cancelled", NSURLErrorFailingURLErrorKey: self.request.URL, NSURLErrorFailingURLStringErrorKey: self.request.URL.absoluteString}]];
// 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 { } else {
// Operation cancelled by user during sending the request // 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 callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorCancelled userInfo:@{NSLocalizedDescriptionKey : @"Operation cancelled by user during sending the request"}]];