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 SDWebImage#134)
- `imageManager:transformDownloadedImage:` let delegate to transform the image prior to cache-in (fix SDWebImage#63, fix SDWebImage#284)
  • Loading branch information
Olivier Poitrey authored and Jack Tihon committed Mar 12, 2013
1 parent 29a3ee3 commit bd4364f
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
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); 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. * The SDWebImageManager is the class behind the UIImageView+WebCache category and likes.
* It ties the asynchronous downloader (SDWebImageDownloader) with the image cache store (SDImageCache). * 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 @interface SDWebImageManager : NSObject


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

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


Expand Down
45 changes: 40 additions & 5 deletions SDWebImage/SDWebImageManager.m
Expand Up @@ -101,17 +101,17 @@ - (NSString *)cacheKeyForURL:(NSURL *)url
[self.runningOperations removeObject:operation]; [self.runningOperations removeObject:operation];
} }
} }
else else if (![self.delegate respondsToSelector:@selector(imageManager:shouldDownloadImageForURL:)] || [self.delegate imageManager:self shouldDownloadImageForURL:url])
{ {
SDWebImageDownloaderOptions downloaderOptions = 0; SDWebImageDownloaderOptions downloaderOptions = 0;
if (options & SDWebImageLowPriority) downloaderOptions |= SDWebImageDownloaderLowPriority; if (options & SDWebImageLowPriority) downloaderOptions |= SDWebImageDownloaderLowPriority;
if (options & SDWebImageProgressiveDownload) downloaderOptions |= SDWebImageDownloaderProgressiveDownload; 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) __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) if (error)
{ {
completedBlock(nil, error, SDImageCacheTypeNone, finished);

if (error.code != NSURLErrorNotConnectedToInternet) if (error.code != NSURLErrorNotConnectedToInternet)
{ {
@synchronized(self.failedURLs) @synchronized(self.failedURLs)
Expand All @@ -120,10 +120,36 @@ - (NSString *)cacheKeyForURL:(NSURL *)url
} }
} }
} }
else if (downloadedImage && finished) else
{ {
const BOOL cacheOnDisk = !(options & SDWebImageCacheMemoryOnly); 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) if (finished)
Expand All @@ -136,6 +162,15 @@ - (NSString *)cacheKeyForURL:(NSURL *)url
}]; }];
operation.cancelBlock = ^{[subOperation cancel];}; 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; return operation;
Expand Down

0 comments on commit bd4364f

Please sign in to comment.