Skip to content

Commit

Permalink
Add SDWebImageManager delegate allowing fine control of manager's c…
Browse files Browse the repository at this point in the history
…ache-in

- `imageManager:shouldDownloadImageForURL:` let delegate to conditionaly block cache-in (fix #134)
- `imageManager:transformDownloadedImage:` let delegate to transform the image prior to cache-in (fix #63, fix #284)
  • Loading branch information
Olivier Poitrey committed Feb 16, 2013
1 parent 6f198ab commit ebd63a8
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 5 deletions.
32 changes: 32 additions & 0 deletions SDWebImage/SDWebImageManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,36 @@ typedef void(^SDWebImageCompletedBlock)(UIImage *image, NSError *error, SDImageC
typedef void(^SDWebImageCompletedWithFinishedBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished);


@class SDWebImageManager;

@protocol SDWebImageManagerDelegate <NSObject>

@optional

/**
* Controls which image should be downloaded when the image is not found in the cache.
*
* @param imageManager The current `SDWebImageManager`
* @param imageURL The url of the image to be downloaded
*
* @return Return NO to prevent the downloading of the image on cache misses. If not implemented, YES is implied.
*/
- (BOOL)imageManager:(SDWebImageManager *)imageManager shouldDownloadImageForURL:(NSURL *)imageURL;

/**
* Allows to transform the image immediately after it has been downloaded and just before to cache it on disk and memory.
* NOTE: This method is called from a global queue in order to not to block the main thread.
*
* @param imageManager The current `SDWebImageManager`
* @param image The image to transform
* @param imageURL The url of the image to transform
*
* @return The transformed image object.
*/
- (UIImage *)imageManager:(SDWebImageManager *)imageManager transformDownloadedImage:(UIImage *)image withURL:(NSURL *)imageURL;

@end

/**
* The SDWebImageManager is the class behind the UIImageView+WebCache category and likes.
* It ties the asynchronous downloader (SDWebImageDownloader) with the image cache store (SDImageCache).
Expand All @@ -61,6 +91,8 @@ typedef void(^SDWebImageCompletedWithFinishedBlock)(UIImage *image, NSError *err
*/
@interface SDWebImageManager : NSObject

@property (weak, nonatomic) id<SDWebImageManagerDelegate> delegate;

@property (strong, nonatomic, readonly) SDImageCache *imageCache;
@property (strong, nonatomic, readonly) SDWebImageDownloader *imageDownloader;

Expand Down
45 changes: 40 additions & 5 deletions SDWebImage/SDWebImageManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,17 @@ - (NSString *)cacheKeyForURL:(NSURL *)url
[self.runningOperations removeObject:operation];
}
}
else
else if (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])
{
SDWebImageDownloaderOptions downloaderOptions = 0;
if (options & SDWebImageLowPriority) downloaderOptions |= SDWebImageDownloaderLowPriority;
if (options & SDWebImageProgressiveDownload) downloaderOptions |= SDWebImageDownloaderProgressiveDownload;
__block id<SDWebImageOperation> subOperation = [self.imageDownloader downloadImageWithURL:url options:downloaderOptions progress:progressBlock completed:^(UIImage *downloadedImage, NSData *data, NSError *error, BOOL finished)
{
completedBlock(downloadedImage, error, SDImageCacheTypeNone, finished);

if (error)
{
completedBlock(nil, error, SDImageCacheTypeNone, finished);

if (error.code != NSURLErrorNotConnectedToInternet)
{
@synchronized(self.failedURLs)
Expand All @@ -120,10 +120,36 @@ - (NSString *)cacheKeyForURL:(NSURL *)url
}
}
}
else if (downloadedImage && finished)
else
{
const BOOL cacheOnDisk = !(options & SDWebImageCacheMemoryOnly);
[self.imageCache storeImage:downloadedImage imageData:data forKey:key toDisk:cacheOnDisk];

if (downloadedImage && [self.delegate respondsToSelector:@selector(imageManager:transformDownloadedImage:withURL:)])
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^
{
UIImage *transformedImage = [self.delegate imageManager:self transformDownloadedImage:downloadedImage withURL:url];

dispatch_async(dispatch_get_main_queue(), ^
{
completedBlock(transformedImage, nil, SDImageCacheTypeNone, finished);
});

if (transformedImage && finished)
{
[self.imageCache storeImage:transformedImage imageData:data forKey:key toDisk:cacheOnDisk];
}
});
}
else
{
completedBlock(downloadedImage, nil, SDImageCacheTypeNone, finished);

if (downloadedImage && finished)
{
[self.imageCache storeImage:downloadedImage imageData:data forKey:key toDisk:cacheOnDisk];
}
}
}

if (finished)
Expand All @@ -136,6 +162,15 @@ - (NSString *)cacheKeyForURL:(NSURL *)url
}];
operation.cancelBlock = ^{[subOperation cancel];};
}
else
{
// Image not in cache and download disallowed by delegate
completedBlock(nil, nil, SDImageCacheTypeNone, YES);
@synchronized(self.runningOperations)
{
[self.runningOperations removeObject:operation];
}
}
}];

return operation;
Expand Down

1 comment on commit ebd63a8

@alexburkhay
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (transformedImage && finished)
{
[self.imageCache storeImage:transformedImage imageData:data forKey:key toDisk:cacheOnDisk];
}

wrong imageData value passed here - input parameter data was imageData for downloaded image ..its not data for transformedImage
u should pass nil here [self.imageCache storeImage:transformedImage imageData:nil forKey:key toDisk:cacheOnDisk];

Please sign in to comment.