Merge pull request #996 from harishkashyap/fix-memory-issues
Adds option to decompress images and select prefetcher Queue
This commit is contained in:
commit
17c3cf3aa0
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue