Addressing comments

This commit is contained in:
Garrett Moon
2016-02-09 14:05:36 -08:00
parent 820390e496
commit 48fc4810cd
6 changed files with 200 additions and 148 deletions

View File

@@ -51,7 +51,7 @@ Pod::Spec.new do |spec|
spec.subspec 'PINRemoteImage' do |pin| spec.subspec 'PINRemoteImage' do |pin|
pin.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_REMOTE_IMAGE=1' } pin.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_REMOTE_IMAGE=1' }
pin.dependency 'PINRemoteImage', '>= 2' pin.dependency 'PINRemoteImage/iOS', '>= 2'
pin.dependency 'AsyncDisplayKit/ASDealloc2MainObject' pin.dependency 'AsyncDisplayKit/ASDealloc2MainObject'
end end

View File

@@ -48,8 +48,8 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
{ {
@private @private
// Core. // Core.
id<ASImageCacheProtocol> _cache; id<ASImageCacheProtocol, ASImageCacheProtocolDeprecated> _cache;
id<ASImageDownloaderProtocol> _downloader; id<ASImageDownloaderProtocol, ASImageDownloaderProtocolDeprecated> _downloader;
__weak id<ASMultiplexImageNodeDelegate> _delegate; __weak id<ASMultiplexImageNodeDelegate> _delegate;
struct { struct {
@@ -85,7 +85,8 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
BOOL _downloaderSupportsNewProtocol; BOOL _downloaderSupportsNewProtocol;
BOOL _downloaderImplementsSetProgress; BOOL _downloaderImplementsSetProgress;
BOOL _downloaderImplementsSetPriority; BOOL _downloaderImplementsSetPriority;
BOOL _cacherSupportsNewProtocol; BOOL _cacheSupportsNewProtocol;
BOOL _cacheSupportsClearing;
} }
//! @abstract Read-write redeclaration of property declared in ASMultiplexImageNode.h. //! @abstract Read-write redeclaration of property declared in ASMultiplexImageNode.h.
@@ -156,13 +157,6 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
*/ */
- (void)_downloadImageWithIdentifier:(id)imageIdentifier URL:(NSURL *)imageURL completion:(void (^)(UIImage *image, NSError *error))completionBlock; - (void)_downloadImageWithIdentifier:(id)imageIdentifier URL:(NSURL *)imageURL completion:(void (^)(UIImage *image, NSError *error))completionBlock;
/**
@abstract Returns a Boolean value indicating whether the downloaded image should be removed when clearing fetched data
@discussion Downloaded image data should only be cleared out if a cache is present
@return YES if an image cache is available; otherwise, NO.
*/
- (BOOL)_shouldClearFetchedImageData;
@end @end
@implementation ASMultiplexImageNode @implementation ASMultiplexImageNode
@@ -176,16 +170,17 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
_cache = cache; _cache = cache;
_downloader = downloader; _downloader = downloader;
NSAssert([downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgress:completion:)] || [downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:)], @"downloader must respond to either downloadImageWithURL:callbackQueue:downloadProgress:completion: or downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:."); ASDisplayNodeAssert([downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgress:completion:)] || [downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:)], @"downloader must respond to either downloadImageWithURL:callbackQueue:downloadProgress:completion: or downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:.");
_downloaderSupportsNewProtocol = [downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgress:completion:)] ? YES : NO; _downloaderSupportsNewProtocol = [downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgress:completion:)];
NSAssert(cache == nil || [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)] || [cache respondsToSelector:@selector(fetchCachedImageWithURL:callbackQueue:completion:)], @"cacher must respond to either cachedImageWithURL:callbackQueue:completion: or fetchCachedImageWithURL:callbackQueue:completion:"); ASDisplayNodeAssert(cache == nil || [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)] || [cache respondsToSelector:@selector(fetchCachedImageWithURL:callbackQueue:completion:)], @"cacher must respond to either cachedImageWithURL:callbackQueue:completion: or fetchCachedImageWithURL:callbackQueue:completion:");
_downloaderImplementsSetProgress = [downloader respondsToSelector:@selector(setProgressImageBlock:callbackQueue:withDownloadIdentifier:)] ? YES : NO; _downloaderImplementsSetProgress = [downloader respondsToSelector:@selector(setProgressImageBlock:callbackQueue:withDownloadIdentifier:)];
_downloaderImplementsSetPriority = [downloader respondsToSelector:@selector(setPriority:withDownloadIdentifier:)] ? YES : NO; _downloaderImplementsSetPriority = [downloader respondsToSelector:@selector(setPriority:withDownloadIdentifier:)];
_cacherSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)] ? YES : NO; _cacheSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)];
_cacheSupportsClearing = [cache respondsToSelector:@selector(clearFetchedImageFromCacheWithURL:)];
self.shouldBypassEnsureDisplay = YES; self.shouldBypassEnsureDisplay = YES;
@@ -220,16 +215,17 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
{ {
[super clearFetchedData]; [super clearFetchedData];
if ([self _shouldClearFetchedImageData]) {
[_phImageRequestOperation cancel]; [_phImageRequestOperation cancel];
[self _setDownloadIdentifier:nil]; [self _setDownloadIdentifier:nil];
if (_cacheSupportsClearing) {
[_cache clearFetchedImageFromCacheWithURL:[_dataSource multiplexImageNode:self URLForImageIdentifier:self.loadedImageIdentifier]];
}
// setting this to nil makes the node fetch images the next time its display starts // setting this to nil makes the node fetch images the next time its display starts
_loadedImageIdentifier = nil; _loadedImageIdentifier = nil;
self.image = nil; self.image = nil;
}
} }
- (void)fetchData - (void)fetchData
@@ -266,6 +262,8 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
} }
} }
/* displayWillStart in ASNetworkImageNode has a very similar implementation. Changes here are likely necessary
in ASNetworkImageNode as well. */
- (void)displayWillStart - (void)displayWillStart
{ {
[super displayWillStart]; [super displayWillStart];
@@ -276,19 +274,37 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
{ {
ASDN::MutexLocker l(_downloadIdentifierLock); ASDN::MutexLocker l(_downloadIdentifierLock);
if (_downloadIdentifier != nil) { if (_downloadIdentifier != nil) {
[_downloader setPriority:ASImageDownloaderPriorityDisplay withDownloadIdentifier:_downloadIdentifier]; [_downloader setPriority:ASImageDownloaderPriorityImminent withDownloadIdentifier:_downloadIdentifier];
}
}
}
}
/* visibilityDidChange in ASNetworkImageNode has a very similar implementation. Changes here are likely necessary
in ASNetworkImageNode as well. */
- (void)visibilityDidChange:(BOOL)isVisible
{
[super visibilityDidChange:isVisible];
if (_downloaderImplementsSetPriority) {
ASDN::MutexLocker l(_downloadIdentifierLock);
if (_downloadIdentifier != nil) {
if (isVisible) {
[_downloader setPriority:ASImageDownloaderPriorityVisible withDownloadIdentifier:_downloadIdentifier];
} else {
[_downloader setPriority:ASImageDownloaderPriorityPreload withDownloadIdentifier:_downloadIdentifier];
} }
} }
} }
if (self.image == nil) {
if (_downloaderImplementsSetProgress) { if (_downloaderImplementsSetProgress) {
{
ASDN::MutexLocker l(_downloadIdentifierLock); ASDN::MutexLocker l(_downloadIdentifierLock);
if (_downloadIdentifier != nil) { if (_downloadIdentifier != nil) {
__weak __typeof__(self) weakSelf = self; __weak __typeof__(self) weakSelf = self;
[_downloader setProgressImageBlock:^(UIImage * _Nonnull progressImage, id _Nullable downloadIdentifier) { ASImageDownloaderProgressImage progress = nil;
if (isVisible) {
progress = ^(UIImage * _Nonnull progressImage, id _Nullable downloadIdentifier) {
__typeof__(self) strongSelf = weakSelf; __typeof__(self) strongSelf = weakSelf;
if (strongSelf == nil) { if (strongSelf == nil) {
return; return;
@@ -296,14 +312,15 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
ASDN::MutexLocker l(strongSelf->_downloadIdentifierLock); ASDN::MutexLocker l(strongSelf->_downloadIdentifierLock);
//Getting a result back for a different download identifier, download must not have been successfully canceled //Getting a result back for a different download identifier, download must not have been successfully canceled
if (![strongSelf->_downloadIdentifier isEqual:downloadIdentifier] && downloadIdentifier != nil) { if (ASObjectIsEqual(strongSelf->_downloadIdentifier, downloadIdentifier) == NO && downloadIdentifier != nil) {
return; return;
} }
strongSelf.image = progressImage; strongSelf.image = progressImage;
} callbackQueue:dispatch_get_main_queue() withDownloadIdentifier:_downloadIdentifier]; };
}
} }
[_downloader setProgressImageBlock:progress callbackQueue:dispatch_get_main_queue() withDownloadIdentifier:_downloadIdentifier];
} }
} }
} }
@@ -695,7 +712,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
ASDisplayNodeAssertNotNil(completionBlock, @"completionBlock is required"); ASDisplayNodeAssertNotNil(completionBlock, @"completionBlock is required");
if (_cache) { if (_cache) {
if (_cacherSupportsNewProtocol) { if (_cacheSupportsNewProtocol) {
[_cache cachedImageWithURL:imageURL callbackQueue:dispatch_get_main_queue() completion:^(UIImage *imageFromCache) { [_cache cachedImageWithURL:imageURL callbackQueue:dispatch_get_main_queue() completion:^(UIImage *imageFromCache) {
completionBlock(imageFromCache); completionBlock(imageFromCache);
}]; }];
@@ -746,7 +763,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
ASDN::MutexLocker l(_downloadIdentifierLock); ASDN::MutexLocker l(_downloadIdentifierLock);
//Getting a result back for a different download identifier, download must not have been successfully canceled //Getting a result back for a different download identifier, download must not have been successfully canceled
if (![_downloadIdentifier isEqual:downloadIdentifier] && downloadIdentifier != nil) { if (ASObjectIsEqual(_downloadIdentifier, downloadIdentifier) == NO && downloadIdentifier != nil) {
return; return;
} }
@@ -811,10 +828,6 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
[self _loadNextImage]; [self _loadNextImage];
} }
- (BOOL)_shouldClearFetchedImageData {
return _cache != nil;
}
@end @end
#if TARGET_OS_IOS #if TARGET_OS_IOS
@implementation NSURL (ASPhotosFrameworkURLs) @implementation NSURL (ASPhotosFrameworkURLs)

View File

@@ -45,19 +45,19 @@ NS_ASSUME_NONNULL_BEGIN
/** /**
* The delegate, which must conform to the <ASNetworkImageNodeDelegate> protocol. * The delegate, which must conform to the <ASNetworkImageNodeDelegate> protocol.
*/ */
@property (nonatomic, weak, readwrite) id<ASNetworkImageNodeDelegate> delegate; @property (atomic, weak, readwrite) id<ASNetworkImageNodeDelegate> delegate;
/** /**
* A placeholder image to display while the URL is loading. * A placeholder image to display while the URL is loading.
*/ */
@property (nullable, nonatomic, strong, readwrite) UIImage *defaultImage; @property (nullable, atomic, strong, readwrite) UIImage *defaultImage;
/** /**
* The URL of a new image to download and display. * The URL of a new image to download and display.
* *
* @discussion Changing this property will reset the displayed image to a placeholder (<defaultImage>) while loading. * @discussion Changing this property will reset the displayed image to a placeholder (<defaultImage>) while loading.
*/ */
@property (nullable, nonatomic, strong, readwrite) NSURL *URL; @property (nullable, atomic, strong, readwrite) NSURL *URL;
/** /**
* Download and display a new image. * Download and display a new image.

View File

@@ -21,8 +21,8 @@
@interface ASNetworkImageNode () @interface ASNetworkImageNode ()
{ {
ASDN::RecursiveMutex _lock; ASDN::RecursiveMutex _lock;
__weak id<ASImageCacheProtocol> _cache; __weak id<ASImageCacheProtocol, ASImageCacheProtocolDeprecated> _cache;
__weak id<ASImageDownloaderProtocol> _downloader; __weak id<ASImageDownloaderProtocol, ASImageDownloaderProtocolDeprecated> _downloader;
// Only access any of these with _lock. // Only access any of these with _lock.
__weak id<ASNetworkImageNodeDelegate> _delegate; __weak id<ASNetworkImageNodeDelegate> _delegate;
@@ -39,7 +39,8 @@
BOOL _downloaderSupportsNewProtocol; BOOL _downloaderSupportsNewProtocol;
BOOL _downloaderImplementsSetProgress; BOOL _downloaderImplementsSetProgress;
BOOL _downloaderImplementsSetPriority; BOOL _downloaderImplementsSetPriority;
BOOL _cacherSupportsNewProtocol; BOOL _cacheSupportsNewProtocol;
BOOL _cacheSupportsClearing;
} }
@end @end
@@ -53,16 +54,17 @@
_cache = cache; _cache = cache;
_downloader = downloader; _downloader = downloader;
NSAssert([downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgress:completion:)] || [downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:)], @"downloader must respond to either downloadImageWithURL:callbackQueue:downloadProgress:completion: or downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:."); ASDisplayNodeAssert([downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgress:completion:)] || [downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:)], @"downloader must respond to either downloadImageWithURL:callbackQueue:downloadProgress:completion: or downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:.");
_downloaderSupportsNewProtocol = [downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgress:completion:)] ? YES : NO; _downloaderSupportsNewProtocol = [downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgress:completion:)];
NSAssert([cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)] || [cache respondsToSelector:@selector(fetchCachedImageWithURL:callbackQueue:completion:)], @"cacher must respond to either cachedImageWithURL:callbackQueue:completion: or fetchCachedImageWithURL:callbackQueue:completion:"); ASDisplayNodeAssert([cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)] || [cache respondsToSelector:@selector(fetchCachedImageWithURL:callbackQueue:completion:)], @"cacher must respond to either cachedImageWithURL:callbackQueue:completion: or fetchCachedImageWithURL:callbackQueue:completion:");
_downloaderImplementsSetProgress = [downloader respondsToSelector:@selector(setProgressImageBlock:callbackQueue:withDownloadIdentifier:)] ? YES : NO; _downloaderImplementsSetProgress = [downloader respondsToSelector:@selector(setProgressImageBlock:callbackQueue:withDownloadIdentifier:)];
_downloaderImplementsSetPriority = [downloader respondsToSelector:@selector(setPriority:withDownloadIdentifier:)] ? YES : NO; _downloaderImplementsSetPriority = [downloader respondsToSelector:@selector(setPriority:withDownloadIdentifier:)];
_cacherSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)] ? YES : NO; _cacheSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)];
_cacheSupportsClearing = [cache respondsToSelector:@selector(clearFetchedImageFromCacheWithURL:)];
_shouldCacheImage = YES; _shouldCacheImage = YES;
self.shouldBypassEnsureDisplay = YES; self.shouldBypassEnsureDisplay = YES;
@@ -150,29 +152,45 @@
return _delegate; return _delegate;
} }
/* displayWillStart in ASMultiplexImageNode has a very similar implementation. Changes here are likely necessary
in ASMultiplexImageNode as well. */
- (void)displayWillStart - (void)displayWillStart
{ {
[super displayWillStart]; [super displayWillStart];
[self fetchData]; [self fetchData];
if (self.image == nil) { if (self.image == nil && _downloaderImplementsSetPriority) {
if (_downloaderImplementsSetPriority) {
{
ASDN::MutexLocker l(_lock); ASDN::MutexLocker l(_lock);
if (_downloadIdentifier != nil) { if (_downloadIdentifier != nil) {
[_downloader setPriority:ASImageDownloaderPriorityDisplay withDownloadIdentifier:_downloadIdentifier]; [_downloader setPriority:ASImageDownloaderPriorityImminent withDownloadIdentifier:_downloadIdentifier];
}
}
}
/* visibilityDidChange in ASMultiplexImageNode has a very similar implementation. Changes here are likely necessary
in ASMultiplexImageNode as well. */
- (void)visibilityDidChange:(BOOL)isVisible
{
if (_downloaderImplementsSetPriority) {
ASDN::MutexLocker l(_lock);
if (_downloadIdentifier != nil) {
if (isVisible) {
[_downloader setPriority:ASImageDownloaderPriorityVisible withDownloadIdentifier:_downloadIdentifier];
} else {
[_downloader setPriority:ASImageDownloaderPriorityPreload withDownloadIdentifier:_downloadIdentifier];
} }
} }
} }
if (_downloaderImplementsSetProgress) { if (_downloaderImplementsSetProgress) {
{
ASDN::MutexLocker l(_lock); ASDN::MutexLocker l(_lock);
if (_downloadIdentifier != nil) { if (_downloadIdentifier != nil) {
__weak __typeof__(self) weakSelf = self; __weak __typeof__(self) weakSelf = self;
[_downloader setProgressImageBlock:^(UIImage * _Nonnull progressImage, id _Nullable downloadIdentifier) { ASImageDownloaderProgressImage progress = nil;
if (isVisible) {
progress = ^(UIImage * _Nonnull progressImage, id _Nullable downloadIdentifier) {
__typeof__(self) strongSelf = weakSelf; __typeof__(self) strongSelf = weakSelf;
if (strongSelf == nil) { if (strongSelf == nil) {
return; return;
@@ -180,14 +198,14 @@
ASDN::MutexLocker l(_lock); ASDN::MutexLocker l(_lock);
//Getting a result back for a different download identifier, download must not have been successfully canceled //Getting a result back for a different download identifier, download must not have been successfully canceled
if (![strongSelf->_downloadIdentifier isEqual:downloadIdentifier] && downloadIdentifier != nil) { if (ASObjectIsEqual(strongSelf->_downloadIdentifier, downloadIdentifier) == NO && downloadIdentifier != nil) {
return; return;
} }
strongSelf.image = progressImage; strongSelf.image = progressImage;
} callbackQueue:dispatch_get_main_queue() withDownloadIdentifier:_downloadIdentifier]; };
}
} }
[_downloader setProgressImageBlock:progress callbackQueue:dispatch_get_main_queue() withDownloadIdentifier:_downloadIdentifier];
} }
} }
} }
@@ -202,6 +220,9 @@
[self _cancelImageDownload]; [self _cancelImageDownload];
self.image = _defaultImage; self.image = _defaultImage;
_imageLoaded = NO; _imageLoaded = NO;
if (_cacheSupportsClearing) {
[_cache clearFetchedImageFromCacheWithURL:_URL];
}
} }
} }
@@ -294,7 +315,7 @@
ASDN::MutexLocker l(strongSelf->_lock); ASDN::MutexLocker l(strongSelf->_lock);
//Getting a result back for a different download identifier, download must not have been successfully canceled //Getting a result back for a different download identifier, download must not have been successfully canceled
if (![strongSelf->_downloadIdentifier isEqual:downloadIdentifier] && downloadIdentifier != nil) { if (ASObjectIsEqual(strongSelf->_downloadIdentifier, downloadIdentifier) == NO && downloadIdentifier != nil) {
return; return;
} }
@@ -333,18 +354,16 @@
} }
}; };
if (_cacherSupportsNewProtocol) { if (_cacheSupportsNewProtocol) {
[_cache cachedImageWithURL:_URL [_cache cachedImageWithURL:_URL
callbackQueue:dispatch_get_main_queue() callbackQueue:dispatch_get_main_queue()
completion:cacheCompletion]; completion:cacheCompletion];
} else { } else {
void (^oldCacheCompletion)(CGImageRef) = ^(CGImageRef image) {
cacheCompletion([UIImage imageWithCGImage:image]);
};
[_cache fetchCachedImageWithURL:_URL [_cache fetchCachedImageWithURL:_URL
callbackQueue:dispatch_get_main_queue() callbackQueue:dispatch_get_main_queue()
completion:oldCacheCompletion]; completion:^(CGImageRef image) {
cacheCompletion([UIImage imageWithCGImage:image]);
}];
} }
} else { } else {
[self _downloadImageWithCompletion:finished]; [self _downloadImageWithCompletion:finished];

View File

@@ -16,12 +16,6 @@ typedef void(^ASImageCacherCompletion)(UIImage * _Nullable imageFromCache);
@protocol ASImageCacheProtocol <NSObject> @protocol ASImageCacheProtocol <NSObject>
@optional @optional
/**
@deprecated This method is deprecated @see cachedImageWithURL:callbackQueue:completion: instead
*/
- (void)fetchCachedImageWithURL:(nullable NSURL *)URL
callbackQueue:(nullable dispatch_queue_t)callbackQueue
completion:(void (^)(CGImageRef _Nullable imageFromCache))completion;
/** /**
@abstract Attempts to fetch an image with the given URL from the cache. @abstract Attempts to fetch an image with the given URL from the cache.
@@ -33,10 +27,17 @@ typedef void(^ASImageCacherCompletion)(UIImage * _Nullable imageFromCache);
@discussion If `URL` is nil, `completion` will be invoked immediately with a nil image. This method should not block @discussion If `URL` is nil, `completion` will be invoked immediately with a nil image. This method should not block
the calling thread as it is likely to be called from the main thread. the calling thread as it is likely to be called from the main thread.
*/ */
- (void)cachedImageWithURL:(nullable NSURL *)URL - (void)cachedImageWithURL:(NSURL *)URL
callbackQueue:(nullable dispatch_queue_t)callbackQueue callbackQueue:(dispatch_queue_t)callbackQueue
completion:(ASImageCacherCompletion)completion; completion:(ASImageCacherCompletion)completion;
/**
@abstract Called during clearFetchedData. Allows the cache to optionally trim items.
@note Depending on your caches implementation you may *not* wish to respond to this method. It is however useful
if you have a memory and disk cache in which case you'll likely want to clear out the memory cache.
*/
- (void)clearFetchedImageFromCacheWithURL:(NSURL *)URL;
@end @end
typedef void(^ASImageDownloaderCompletion)(UIImage * _Nullable image, NSError * _Nullable error, id _Nullable downloadIdentifier); typedef void(^ASImageDownloaderCompletion)(UIImage * _Nullable image, NSError * _Nullable error, id _Nullable downloadIdentifier);
@@ -44,8 +45,9 @@ typedef void(^ASImageDownloaderProgress)(CGFloat progress);
typedef void(^ASImageDownloaderProgressImage)(UIImage *progressImage, id _Nullable downloadIdentifier); typedef void(^ASImageDownloaderProgressImage)(UIImage *progressImage, id _Nullable downloadIdentifier);
typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) { typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) {
ASImageDownloaderPriorityNormal = 0, ASImageDownloaderPriorityPreload = 0,
ASImageDownloaderPriorityDisplay, ASImageDownloaderPriorityImminent,
ASImageDownloaderPriorityVisible
}; };
@protocol ASImageDownloaderProtocol <NSObject> @protocol ASImageDownloaderProtocol <NSObject>
@@ -62,15 +64,7 @@ typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) {
@optional @optional
//You must implement one of the two following methods //You must implement the following method OR the deprecated method at the bottom
/**
@deprecated This method is deprecated @see downloadImageWithURL:callbackQueue:downloadProgress:completion: instead
*/
- (nullable id)downloadImageWithURL:(NSURL *)URL
callbackQueue:(nullable dispatch_queue_t)callbackQueue
downloadProgressBlock:(void (^ _Nullable)(CGFloat progress))downloadProgressBlock
completion:(void (^ _Nullable)(CGImageRef _Nullable image, NSError * _Nullable error))completion;
/** /**
@abstract Downloads an image with the given URL. @abstract Downloads an image with the given URL.
@@ -113,4 +107,29 @@ withDownloadIdentifier:(id)downloadIdentifier;
@end @end
@protocol ASImageDownloaderProtocolDeprecated <ASImageDownloaderProtocol>
@optional
/**
@deprecated This method is deprecated @see downloadImageWithURL:callbackQueue:downloadProgress:completion: instead
*/
- (nullable id)downloadImageWithURL:(NSURL *)URL
callbackQueue:(nullable dispatch_queue_t)callbackQueue
downloadProgressBlock:(void (^ _Nullable)(CGFloat progress))downloadProgressBlock
completion:(void (^ _Nullable)(CGImageRef _Nullable image, NSError * _Nullable error))completion;
@end
@protocol ASImageCacheProtocolDeprecated <ASImageCacheProtocol>
@optional
/**
@deprecated This method is deprecated @see cachedImageWithURL:callbackQueue:completion: instead
*/
- (void)fetchCachedImageWithURL:(nullable NSURL *)URL
callbackQueue:(nullable dispatch_queue_t)callbackQueue
completion:(void (^)(CGImageRef _Nullable imageFromCache))completion;
@end
NS_ASSUME_NONNULL_END NS_ASSUME_NONNULL_END

View File

@@ -8,6 +8,9 @@
#ifdef PIN_REMOTE_IMAGE #ifdef PIN_REMOTE_IMAGE
#import "ASPINRemoteImageDownloader.h" #import "ASPINRemoteImageDownloader.h"
#import "ASAssert.h"
#import <PINRemoteImage/PINRemoteImageManager.h> #import <PINRemoteImage/PINRemoteImageManager.h>
#import <PINCache/PINCache.h> #import <PINCache/PINCache.h>
@@ -29,28 +32,18 @@
callbackQueue:(dispatch_queue_t)callbackQueue callbackQueue:(dispatch_queue_t)callbackQueue
completion:(void (^)(CGImageRef imageFromCache))completion completion:(void (^)(CGImageRef imageFromCache))completion
{ {
NSString *key = [[PINRemoteImageManager sharedImageManager] cacheKeyForURL:URL processorKey:nil]; //We do not check the cache here and instead check it in downloadImageWithURL to avoid checking the cache twice.
UIImage *image = [[[[PINRemoteImageManager sharedImageManager] cache] memoryCache] objectForKey:key];
dispatch_async(callbackQueue, ^{ dispatch_async(callbackQueue, ^{
completion([image CGImage]); completion(nil);
}); });
} }
/** - (void)clearFetchedImageFromCacheWithURL:(NSURL *)URL
@abstract Downloads an image with the given URL. {
@param URL The URL of the image to download. NSString *key = [[PINRemoteImageManager sharedImageManager] cacheKeyForURL:URL processorKey:nil];
@param callbackQueue The queue to call `downloadProgressBlock` and `completion` on. If this value is nil, both blocks [[[[PINRemoteImageManager sharedImageManager] cache] memoryCache] removeObjectForKey:key];
will be invoked on the main-queue. }
@param downloadProgressBlock The block to be invoked when the download of `URL` progresses.
@param progress The progress of the download, in the range of (0.0, 1.0), inclusive.
@param completion The block to be invoked when the download has completed, or has failed.
@param image The image that was downloaded, if the image could be successfully downloaded; nil otherwise.
@param error An error describing why the download of `URL` failed, if the download failed; nil otherwise.
@discussion This method is likely to be called on the main thread, so any custom implementations should make sure to background any expensive download operations.
@result An opaque identifier to be used in canceling the download, via `cancelImageDownloadForIdentifier:`. You must
retain the identifier if you wish to use it later.
*/
- (nullable id)downloadImageWithURL:(NSURL *)URL - (nullable id)downloadImageWithURL:(NSURL *)URL
callbackQueue:(dispatch_queue_t)callbackQueue callbackQueue:(dispatch_queue_t)callbackQueue
downloadProgress:(void (^)(CGFloat progress))downloadProgressBlock downloadProgress:(void (^)(CGFloat progress))downloadProgressBlock
@@ -63,21 +56,15 @@
}]; }];
} }
/**
@abstract Cancels an image download.
@param downloadIdentifier The opaque download identifier object returned from
`downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:`.
@discussion This method has no effect if `downloadIdentifier` is nil.
*/
- (void)cancelImageDownloadForIdentifier:(id)downloadIdentifier - (void)cancelImageDownloadForIdentifier:(id)downloadIdentifier
{ {
NSAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID"); ASDisplayNodeAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID");
[[PINRemoteImageManager sharedImageManager] cancelTaskWithUUID:downloadIdentifier]; [[PINRemoteImageManager sharedImageManager] cancelTaskWithUUID:downloadIdentifier];
} }
- (void)setProgressImageBlock:(ASImageDownloaderProgressImage)progressBlock callbackQueue:(dispatch_queue_t)callbackQueue withDownloadIdentifier:(id)downloadIdentifier - (void)setProgressImageBlock:(ASImageDownloaderProgressImage)progressBlock callbackQueue:(dispatch_queue_t)callbackQueue withDownloadIdentifier:(id)downloadIdentifier
{ {
NSAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID"); ASDisplayNodeAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID");
[[PINRemoteImageManager sharedImageManager] setProgressCallback:^(PINRemoteImageManagerResult * _Nonnull result) { [[PINRemoteImageManager sharedImageManager] setProgressCallback:^(PINRemoteImageManagerResult * _Nonnull result) {
dispatch_async(callbackQueue, ^{ dispatch_async(callbackQueue, ^{
@@ -88,9 +75,23 @@
- (void)setPriority:(ASImageDownloaderPriority)priority withDownloadIdentifier:(id)downloadIdentifier - (void)setPriority:(ASImageDownloaderPriority)priority withDownloadIdentifier:(id)downloadIdentifier
{ {
NSAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID"); ASDisplayNodeAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID");
[[PINRemoteImageManager sharedImageManager] setPriority:PINRemoteImageManagerPriorityHigh ofTaskWithUUID:downloadIdentifier]; PINRemoteImageManagerPriority pi_priority = PINRemoteImageManagerPriorityMedium;
switch (priority) {
case ASImageDownloaderPriorityPreload:
pi_priority = PINRemoteImageManagerPriorityMedium;
break;
case ASImageDownloaderPriorityImminent:
pi_priority = PINRemoteImageManagerPriorityHigh;
break;
case ASImageDownloaderPriorityVisible:
pi_priority = PINRemoteImageManagerPriorityVeryHigh;
break;
}
[[PINRemoteImageManager sharedImageManager] setPriority:pi_priority ofTaskWithUUID:downloadIdentifier];
} }
@end @end