From b5bb74bf96ca501a10465b2477e345cad5a492b1 Mon Sep 17 00:00:00 2001 From: Olivier Poitrey Date: Tue, 6 Nov 2012 10:03:59 +0100 Subject: [PATCH] Ensure every data manipulation performed in NSURLConnection delegates are handled in the global background queue --- SDWebImage/SDWebImageDownloaderOperation.m | 126 +++++++++++---------- 1 file changed, 64 insertions(+), 62 deletions(-) diff --git a/SDWebImage/SDWebImageDownloaderOperation.m b/SDWebImage/SDWebImageDownloaderOperation.m index ec1373dc..26c218ab 100644 --- a/SDWebImage/SDWebImageDownloaderOperation.m +++ b/SDWebImage/SDWebImageDownloaderOperation.m @@ -162,95 +162,97 @@ - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { - [self.imageData appendData:data]; - - if ((self.options & SDWebImageDownloaderProgressiveDownload) && self.expectedSize > 0 && self.completedBlock) + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^ { - // The following code is from http://www.cocoaintheshell.com/2011/05/progressive-images-download-imageio/ - // Thanks to the author @Nyx0uf + [self.imageData appendData:data]; - // Get the total bytes downloaded - const NSUInteger totalSize = self.imageData.length; - - // Update the data source, we must pass ALL the data, not just the new bytes - CGImageSourceRef imageSource = CGImageSourceCreateIncremental(NULL); - CGImageSourceUpdateData(imageSource, (__bridge CFDataRef)self.imageData, totalSize == self.expectedSize); - - if (width + height == 0) + if ((self.options & SDWebImageDownloaderProgressiveDownload) && self.expectedSize > 0 && self.completedBlock) { - CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); - if (properties) + // The following code is from http://www.cocoaintheshell.com/2011/05/progressive-images-download-imageio/ + // Thanks to the author @Nyx0uf + + // Get the total bytes downloaded + const NSUInteger totalSize = self.imageData.length; + + // Update the data source, we must pass ALL the data, not just the new bytes + CGImageSourceRef imageSource = CGImageSourceCreateIncremental(NULL); + CGImageSourceUpdateData(imageSource, (__bridge CFDataRef)self.imageData, totalSize == self.expectedSize); + + if (width + height == 0) { - CFTypeRef val = CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight); - if (val) CFNumberGetValue(val, kCFNumberLongType, &height); - val = CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth); - if (val) CFNumberGetValue(val, kCFNumberLongType, &width); - CFRelease(properties); + CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); + if (properties) + { + CFTypeRef val = CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight); + if (val) CFNumberGetValue(val, kCFNumberLongType, &height); + val = CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth); + if (val) CFNumberGetValue(val, kCFNumberLongType, &width); + CFRelease(properties); + } } - } - if (width + height > 0 && totalSize < self.expectedSize) - { - // Create the image - CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL); + if (width + height > 0 && totalSize < self.expectedSize) + { + // Create the image + CGImageRef partialImageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL); #ifdef TARGET_OS_IPHONE - // Workaround for iOS anamorphic image - if (partialImageRef) - { - const size_t partialHeight = CGImageGetHeight(partialImageRef); - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGContextRef bmContext = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); - CGColorSpaceRelease(colorSpace); - if (bmContext) + // Workaround for iOS anamorphic image + if (partialImageRef) { - CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = width, .size.height = partialHeight}, partialImageRef); - CGImageRelease(partialImageRef); - partialImageRef = CGBitmapContextCreateImage(bmContext); - CGContextRelease(bmContext); + const size_t partialHeight = CGImageGetHeight(partialImageRef); + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef bmContext = CGBitmapContextCreate(NULL, width, height, 8, width * 4, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedFirst); + CGColorSpaceRelease(colorSpace); + if (bmContext) + { + CGContextDrawImage(bmContext, (CGRect){.origin.x = 0.0f, .origin.y = 0.0f, .size.width = width, .size.height = partialHeight}, partialImageRef); + CGImageRelease(partialImageRef); + partialImageRef = CGBitmapContextCreateImage(bmContext); + CGContextRelease(bmContext); + } + else + { + CGImageRelease(partialImageRef); + partialImageRef = nil; + } } - else - { - CGImageRelease(partialImageRef); - partialImageRef = nil; - } - } #endif - if (partialImageRef) - { - UIImage *image = [UIImage decodedImageWithImage:SDScaledImageForPath(self.request.URL.absoluteString, [UIImage imageWithCGImage:partialImageRef])]; - CGImageRelease(partialImageRef); - self.completedBlock(image, nil, NO); + if (partialImageRef) + { + UIImage *image = [UIImage decodedImageWithImage:SDScaledImageForPath(self.request.URL.absoluteString, [UIImage imageWithCGImage:partialImageRef])]; + CGImageRelease(partialImageRef); + self.completedBlock(image, nil, NO); + } } - } - CFRelease(imageSource); - } + CFRelease(imageSource); + } + }); } - (void)connectionDidFinishLoading:(NSURLConnection *)aConnection { self.connection = nil; - [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:nil]; - - if (self.completedBlock) + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^ { - __block SDWebImageDownloaderCompletedBlock completionBlock = self.completedBlock; - UIImage *image = SDScaledImageForPath(self.request.URL.absoluteString, self.imageData); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ + [[NSNotificationCenter defaultCenter] postNotificationName:SDWebImageDownloadStopNotification object:nil]; + + if (self.completedBlock) { - UIImage *decodedImage = [UIImage decodedImageWithImage:image]; + __block SDWebImageDownloaderCompletedBlock completionBlock = self.completedBlock; + UIImage *image = [UIImage decodedImageWithImage:SDScaledImageForPath(self.request.URL.absoluteString, self.imageData)]; dispatch_async(dispatch_get_main_queue(), ^ { - completionBlock(decodedImage, nil, YES); + completionBlock(image, nil, YES); completionBlock = nil; }); - }); - } + } - [self done]; + [self done]; + }); } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error