Authored by Olivier Poitrey

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

Adds option to decompress images and select prefetcher Queue
... ... @@ -37,6 +37,12 @@ typedef void(^SDWebImageCalculateSizeBlock)(NSUInteger fileCount, NSUInteger tot
@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.
*/
@property (assign, nonatomic) NSUInteger maxMemoryCost;
... ...
... ... @@ -77,6 +77,9 @@ BOOL ImageDataHasPNGPreffix(NSData *data) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
_diskCachePath = [paths[0] stringByAppendingPathComponent:fullNamespace];
// Set decompression to YES
_shouldDecompressImages = YES;
dispatch_sync(_ioQueue, ^{
_fileManager = [NSFileManager new];
});
... ... @@ -266,7 +269,9 @@ BOOL ImageDataHasPNGPreffix(NSData *data) {
if (data) {
UIImage *image = [UIImage sd_imageWithData:data];
image = [self scaledImageForKey:key image:image];
image = [UIImage decodedImageWithImage:image];
if (self.shouldDecompressImages) {
image = [UIImage decodedImageWithImage:image];
}
return image;
}
else {
... ...
... ... @@ -49,8 +49,6 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
* Put the image in the high priority queue.
*/
SDWebImageDownloaderHighPriority = 1 << 7,
};
typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
... ... @@ -79,12 +77,17 @@ typedef NSDictionary *(^SDWebImageDownloaderHeadersFilterBlock)(NSURL *url, NSDi
*/
@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;
/**
* Shows the current amount of downloads that still need to be downloaded
*/
@property (readonly, nonatomic) NSUInteger currentDownloadCount;
... ...
... ... @@ -65,6 +65,7 @@ static NSString *const kCompletedCallbackKey = @"completed";
- (id)init {
if ((self = [super init])) {
_operationClass = [SDWebImageDownloaderOperation class];
_shouldDecompressImages = YES;
_executionOrder = SDWebImageDownloaderFIFOExecutionOrder;
_downloadQueue = [NSOperationQueue new];
_downloadQueue.maxConcurrentOperationCount = 6;
... ... @@ -166,6 +167,7 @@ static NSString *const kCompletedCallbackKey = @"completed";
[sself.URLCallbacks removeObjectForKey:url];
});
}];
operation.shouldDecompressImages = wself.shouldDecompressImages;
if (wself.username && wself.password) {
operation.credential = [NSURLCredential credentialWithUser:wself.username password:wself.password persistence:NSURLCredentialPersistenceForSession];
... ...
... ... @@ -17,6 +17,9 @@
*/
@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.
*
... ...
... ... @@ -47,6 +47,7 @@
cancelled:(SDWebImageNoParamsBlock)cancelBlock {
if ((self = [super init])) {
_request = request;
_shouldDecompressImages = YES;
_shouldUseCredentialStorage = YES;
_options = options;
_progressBlock = [progressBlock copy];
... ... @@ -294,7 +295,12 @@
UIImage *image = [UIImage imageWithCGImage:partialImageRef scale:1 orientation:orientation];
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
UIImage *scaledImage = [self scaledImageForKey:key image:image];
image = [UIImage decodedImageWithImage:scaledImage];
if (self.shouldDecompressImages) {
image = [UIImage decodedImageWithImage:scaledImage];
}
else {
image = scaledImage;
}
CGImageRelease(partialImageRef);
dispatch_main_sync_safe(^{
if (self.completedBlock) {
... ... @@ -365,7 +371,9 @@
// Do not force decoding animated GIFs
if (!image.images) {
image = [UIImage decodedImageWithImage:image];
if (self.shouldDecompressImages) {
image = [UIImage decodedImageWithImage:image];
}
}
if (CGSizeEqualToSize(image.size, CGSizeZero)) {
completionBlock(nil, nil, [NSError errorWithDomain:@"SDWebImageErrorDomain" code:0 userInfo:@{NSLocalizedDescriptionKey : @"Downloaded image has 0 pixels"}], YES);
... ...
... ... @@ -58,6 +58,11 @@ typedef void(^SDWebImagePrefetcherCompletionBlock)(NSUInteger noOfFinishedUrls,
*/
@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;
/**
... ...
... ... @@ -40,6 +40,7 @@
if ((self = [super init])) {
_manager = [SDWebImageManager new];
_options = SDWebImageLowPriority;
_prefetcherQueue = dispatch_get_main_queue();
self.maxConcurrentDownloads = 3;
}
return self;
... ... @@ -82,9 +83,8 @@
totalCount:self.prefetchURLs.count
];
}
if (self.prefetchURLs.count > self.requestedCount) {
dispatch_async(dispatch_get_main_queue(), ^{
dispatch_async(self.prefetcherQueue, ^{
[self startPrefetchingAtIndex:self.requestedCount];
});
}
... ...