Change access the imageData in NSURLSession delegate queue to solve non thread-s…
…afe issue. Also, ensure imageData in completion block is immutable to avoid accident modification from the other queue
Showing
1 changed file
with
19 additions
and
5 deletions
@@ -228,7 +228,20 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary; | @@ -228,7 +228,20 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary; | ||
228 | [weakSelf.callbackBlocks removeAllObjects]; | 228 | [weakSelf.callbackBlocks removeAllObjects]; |
229 | }); | 229 | }); |
230 | self.dataTask = nil; | 230 | self.dataTask = nil; |
231 | - self.imageData = nil; | 231 | + |
232 | + NSOperationQueue *delegateQueue; | ||
233 | + if (self.unownedSession) { | ||
234 | + delegateQueue = self.unownedSession.delegateQueue; | ||
235 | + } else { | ||
236 | + delegateQueue = self.ownedSession.delegateQueue; | ||
237 | + } | ||
238 | + if (delegateQueue) { | ||
239 | + NSAssert(delegateQueue.maxConcurrentOperationCount == 1, @"NSURLSession delegate queue should be a serial queue"); | ||
240 | + [delegateQueue addOperationWithBlock:^{ | ||
241 | + weakSelf.imageData = nil; | ||
242 | + }]; | ||
243 | + } | ||
244 | + | ||
232 | if (self.ownedSession) { | 245 | if (self.ownedSession) { |
233 | [self.ownedSession invalidateAndCancel]; | 246 | [self.ownedSession invalidateAndCancel]; |
234 | self.ownedSession = nil; | 247 | self.ownedSession = nil; |
@@ -427,8 +440,9 @@ didReceiveResponse:(NSURLResponse *)response | @@ -427,8 +440,9 @@ didReceiveResponse:(NSURLResponse *)response | ||
427 | * the response data will be nil. | 440 | * the response data will be nil. |
428 | * So we don't need to check the cache option here, since the system will obey the cache option | 441 | * So we don't need to check the cache option here, since the system will obey the cache option |
429 | */ | 442 | */ |
430 | - if (self.imageData) { | ||
431 | - UIImage *image = [UIImage sd_imageWithData:self.imageData]; | 443 | + NSData *imageData = [self.imageData copy]; |
444 | + if (imageData) { | ||
445 | + UIImage *image = [UIImage sd_imageWithData:imageData]; | ||
432 | NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL]; | 446 | NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL]; |
433 | image = [self scaledImageForKey:key image:image]; | 447 | image = [self scaledImageForKey:key image:image]; |
434 | 448 | ||
@@ -438,7 +452,7 @@ didReceiveResponse:(NSURLResponse *)response | @@ -438,7 +452,7 @@ didReceiveResponse:(NSURLResponse *)response | ||
438 | if (self.options & SDWebImageDownloaderScaleDownLargeImages) { | 452 | if (self.options & SDWebImageDownloaderScaleDownLargeImages) { |
439 | #if SD_UIKIT || SD_WATCH | 453 | #if SD_UIKIT || SD_WATCH |
440 | image = [UIImage decodedAndScaledDownImageWithImage:image]; | 454 | image = [UIImage decodedAndScaledDownImageWithImage:image]; |
441 | - [self.imageData setData:UIImagePNGRepresentation(image)]; | 455 | + imageData = UIImagePNGRepresentation(image); |
442 | #endif | 456 | #endif |
443 | } else { | 457 | } else { |
444 | image = [UIImage decodedImageWithImage:image]; | 458 | image = [UIImage decodedImageWithImage:image]; |
@@ -448,7 +462,7 @@ didReceiveResponse:(NSURLResponse *)response | @@ -448,7 +462,7 @@ didReceiveResponse:(NSURLResponse *)response | ||
448 | if (CGSizeEqualToSize(image.size, CGSizeZero)) { | 462 | if (CGSizeEqualToSize(image.size, CGSizeZero)) { |
449 | [self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]]; | 463 | [self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}]]; |
450 | } else { | 464 | } else { |
451 | - [self callCompletionBlocksWithImage:image imageData:self.imageData error:nil finished:YES]; | 465 | + [self callCompletionBlocksWithImage:image imageData:imageData error:nil finished:YES]; |
452 | } | 466 | } |
453 | } else { | 467 | } else { |
454 | [self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}]]; | 468 | [self callCompletionBlocksWithError:[NSError errorWithDomain:SDWebImageErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey : @"Image data is nil"}]]; |
-
Please register or login to post a comment