Merge pull request #996 from harishkashyap/fix-memory-issues

Adds option to decompress images and select prefetcher Queue
This commit is contained in:
Olivier Poitrey 2015-02-25 07:54:44 -08:00
commit 17c3cf3aa0
8 changed files with 40 additions and 8 deletions

View File

@ -36,6 +36,12 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
*/ */
@interface SDImageCache : NSObject @interface SDImageCache : NSObject
/**
* Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
* Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
*/
@property (assign, nonatomic) BOOL shouldDecompressImages;
/** /**
* The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory. * The maximum "total cost" of the in-memory image cache. The cost function is the number of pixels held in memory.
*/ */

View File

@ -77,6 +77,9 @@ BOOL ImageDataHasPNGPreffix(NSData *data) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
_diskCachePath = [paths[0] stringByAppendingPathComponent:fullNamespace]; _diskCachePath = [paths[0] stringByAppendingPathComponent:fullNamespace];
// Set decompression to YES
_shouldDecompressImages = YES;
dispatch_sync(_ioQueue, ^{ dispatch_sync(_ioQueue, ^{
_fileManager = [NSFileManager new]; _fileManager = [NSFileManager new];
}); });
@ -266,7 +269,9 @@ BOOL ImageDataHasPNGPreffix(NSData *data) {
if (data) { if (data) {
UIImage *image = [UIImage sd_imageWithData:data]; UIImage *image = [UIImage sd_imageWithData:data];
image = [self scaledImageForKey:key image:image]; image = [self scaledImageForKey:key image:image];
image = [UIImage decodedImageWithImage:image]; if (self.shouldDecompressImages) {
image = [UIImage decodedImageWithImage:image];
}
return image; return image;
} }
else { else {

View File

@ -49,8 +49,6 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
* Put the image in the high priority queue. * Put the image in the high priority queue.
*/ */
SDWebImageDownloaderHighPriority = 1 << 7, SDWebImageDownloaderHighPriority = 1 << 7,
}; };
typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) { typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
@ -79,12 +77,17 @@ typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDi
*/ */
@interface SDWebImageDownloader : NSObject @interface SDWebImageDownloader : NSObject
/**
* Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
* Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
*/
@property (assign, nonatomic) BOOL shouldDecompressImages;
@property (assign, nonatomic) NSInteger maxConcurrentDownloads; @property (assign, nonatomic) NSInteger maxConcurrentDownloads;
/** /**
* Shows the current amount of downloads that still need to be downloaded * Shows the current amount of downloads that still need to be downloaded
*/ */
@property (readonly, nonatomic) NSUInteger currentDownloadCount; @property (readonly, nonatomic) NSUInteger currentDownloadCount;

View File

@ -65,6 +65,7 @@ static NSString *const kCompletedCallbackKey = @"completed";
- (id)init { - (id)init {
if ((self = [super init])) { if ((self = [super init])) {
_operationClass = [SDWebImageDownloaderOperation class]; _operationClass = [SDWebImageDownloaderOperation class];
_shouldDecompressImages = YES;
_executionOrder = SDWebImageDownloaderFIFOExecutionOrder; _executionOrder = SDWebImageDownloaderFIFOExecutionOrder;
_downloadQueue = [NSOperationQueue new]; _downloadQueue = [NSOperationQueue new];
_downloadQueue.maxConcurrentOperationCount = 6; _downloadQueue.maxConcurrentOperationCount = 6;
@ -166,6 +167,7 @@ static NSString *const kCompletedCallbackKey = @"completed";
[sself.URLCallbacks removeObjectForKey:url]; [sself.URLCallbacks removeObjectForKey:url];
}); });
}]; }];
operation.shouldDecompressImages = wself.shouldDecompressImages;
if (wself.username && wself.password) { if (wself.username && wself.password) {
operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession]; operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession];

View File

@ -17,6 +17,9 @@
*/ */
@property (strong, nonatomic, readonly) NSURLRequest *request; @property (strong, nonatomic, readonly) NSURLRequest *request;
@property (assign, nonatomic) BOOL shouldDecompressImages;
/** /**
* Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default. * Whether the URL connection should consult the credential storage for authenticating the connection. `YES` by default.
* *

View File

@ -47,6 +47,7 @@
cancelled:(SDWebImageNoParamsBlock)cancelBlock { cancelled:(SDWebImageNoParamsBlock)cancelBlock {
if ((self = [super init])) { if ((self = [super init])) {
_request = request; _request = request;
_shouldDecompressImages = YES;
_shouldUseCredentialStorage = YES; _shouldUseCredentialStorage = YES;
_options = options; _options = options;
_progressBlock = [progressBlock copy]; _progressBlock = [progressBlock copy];
@ -294,7 +295,12 @@
UIImage *image = [UIImage imageWithCGImage:partialImageRef scale:1 orientation:orientation]; UIImage *image = [UIImage imageWithCGImage:partialImageRef scale:1 orientation:orientation];
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL]; NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
UIImage *scaledImage = [self scaledImageForKey:key image:image]; UIImage *scaledImage = [self scaledImageForKey:key image:image];
image = [UIImage decodedImageWithImage:scaledImage]; if (self.shouldDecompressImages) {
image = [UIImage decodedImageWithImage:scaledImage];
}
else {
image = scaledImage;
}
CGImageRelease(partialImageRef); CGImageRelease(partialImageRef);
dispatch_main_sync_safe(^{ dispatch_main_sync_safe(^{
if (self.completedBlock) { if (self.completedBlock) {
@ -365,7 +371,9 @@
// Do not force decoding animated GIFs // Do not force decoding animated GIFs
if (!image.images) { if (!image.images) {
image = [UIImage decodedImageWithImage:image]; if (self.shouldDecompressImages) {
image = [UIImage decodedImageWithImage:image];
}
} }
if (CGSizeEqualToSize(image.size, CGSizeZero)) { if (CGSizeEqualToSize(image.size, CGSizeZero)) {
completionBlock(nil, nil, [NSError errorWithDomain:@"SDWebImageErrorDomain" code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}], YES); completionBlock(nil, nil, [NSError errorWithDomain:@"SDWebImageErrorDomain" code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}], YES);

View File

@ -58,6 +58,11 @@ typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls,
*/ */
@property (nonatomic, assign) SDWebImageOptions options; @property (nonatomic, assign) SDWebImageOptions options;
/**
* Queue options for Prefetcher. Defaults to Main Queue.
*/
@property (nonatomic, assign) dispatch_queue_t prefetcherQueue;
@property (weak, nonatomic) id <SDWebImagePrefetcherDelegate> delegate; @property (weak, nonatomic) id <SDWebImagePrefetcherDelegate> delegate;
/** /**

View File

@ -40,6 +40,7 @@
if ((self = [super init])) { if ((self = [super init])) {
_manager = [SDWebImageManager new]; _manager = [SDWebImageManager new];
_options = SDWebImageLowPriority; _options = SDWebImageLowPriority;
_prefetcherQueue = dispatch_get_main_queue();
self.maxConcurrentDownloads = 3; self.maxConcurrentDownloads = 3;
} }
return self; return self;
@ -82,9 +83,8 @@
totalCount:self.prefetchURLs.count totalCount:self.prefetchURLs.count
]; ];
} }
if (self.prefetchURLs.count > self.requestedCount) { if (self.prefetchURLs.count > self.requestedCount) {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(self.prefetcherQueue, ^{
[self startPrefetchingAtIndex:self.requestedCount]; [self startPrefetchingAtIndex:self.requestedCount];
}); });
} }