diff --git a/AsyncDisplayKit.podspec b/AsyncDisplayKit.podspec index 263aee5aa6..4872c47f84 100644 --- a/AsyncDisplayKit.podspec +++ b/AsyncDisplayKit.podspec @@ -51,7 +51,7 @@ Pod::Spec.new do |spec| spec.subspec 'PINRemoteImage' do |pin| pin.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_REMOTE_IMAGE=1' } - pin.dependency 'PINRemoteImage', '>= 2' + pin.dependency 'PINRemoteImage/iOS', '>= 2' pin.dependency 'AsyncDisplayKit/ASDealloc2MainObject' end diff --git a/AsyncDisplayKit/ASMultiplexImageNode.mm b/AsyncDisplayKit/ASMultiplexImageNode.mm index 526d1be1ef..c5e33cbcab 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.mm +++ b/AsyncDisplayKit/ASMultiplexImageNode.mm @@ -48,8 +48,8 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent { @private // Core. - id _cache; - id _downloader; + id _cache; + id _downloader; __weak id _delegate; struct { @@ -85,7 +85,8 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent BOOL _downloaderSupportsNewProtocol; BOOL _downloaderImplementsSetProgress; BOOL _downloaderImplementsSetPriority; - BOOL _cacherSupportsNewProtocol; + BOOL _cacheSupportsNewProtocol; + BOOL _cacheSupportsClearing; } //! @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; -/** - @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 @implementation ASMultiplexImageNode @@ -176,16 +170,17 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent _cache = cache; _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; - _downloaderImplementsSetPriority = [downloader respondsToSelector:@selector(setPriority:withDownloadIdentifier:)] ? YES : NO; + _downloaderImplementsSetProgress = [downloader respondsToSelector:@selector(setProgressImageBlock:callbackQueue:withDownloadIdentifier:)]; + _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; @@ -220,16 +215,17 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent { [super clearFetchedData]; - if ([self _shouldClearFetchedImageData]) { - - [_phImageRequestOperation cancel]; + [_phImageRequestOperation cancel]; - [self _setDownloadIdentifier:nil]; - - // setting this to nil makes the node fetch images the next time its display starts - _loadedImageIdentifier = nil; - self.image = 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 + _loadedImageIdentifier = nil; + self.image = nil; } - (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 { [super displayWillStart]; @@ -276,34 +274,53 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent { ASDN::MutexLocker l(_downloadIdentifierLock); 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) { - { - ASDN::MutexLocker l(_downloadIdentifierLock); - - if (_downloadIdentifier != nil) { - __weak __typeof__(self) weakSelf = self; - [_downloader setProgressImageBlock:^(UIImage * _Nonnull progressImage, id _Nullable downloadIdentifier) { - __typeof__(self) strongSelf = weakSelf; - if (strongSelf == nil) { - return; - } - - ASDN::MutexLocker l(strongSelf->_downloadIdentifierLock); - //Getting a result back for a different download identifier, download must not have been successfully canceled - if (![strongSelf->_downloadIdentifier isEqual:downloadIdentifier] && downloadIdentifier != nil) { - return; - } - - strongSelf.image = progressImage; - } callbackQueue:dispatch_get_main_queue() withDownloadIdentifier:_downloadIdentifier]; - } + if (_downloaderImplementsSetProgress) { + ASDN::MutexLocker l(_downloadIdentifierLock); + + if (_downloadIdentifier != nil) { + __weak __typeof__(self) weakSelf = self; + ASImageDownloaderProgressImage progress = nil; + if (isVisible) { + progress = ^(UIImage * _Nonnull progressImage, id _Nullable downloadIdentifier) { + __typeof__(self) strongSelf = weakSelf; + if (strongSelf == nil) { + return; + } + + ASDN::MutexLocker l(strongSelf->_downloadIdentifierLock); + //Getting a result back for a different download identifier, download must not have been successfully canceled + if (ASObjectIsEqual(strongSelf->_downloadIdentifier, downloadIdentifier) == NO && downloadIdentifier != nil) { + return; + } + + strongSelf.image = progressImage; + }; } + + [_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"); if (_cache) { - if (_cacherSupportsNewProtocol) { + if (_cacheSupportsNewProtocol) { [_cache cachedImageWithURL:imageURL callbackQueue:dispatch_get_main_queue() completion:^(UIImage *imageFromCache) { completionBlock(imageFromCache); }]; @@ -746,7 +763,7 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent ASDN::MutexLocker l(_downloadIdentifierLock); //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; } @@ -811,10 +828,6 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent [self _loadNextImage]; } -- (BOOL)_shouldClearFetchedImageData { - return _cache != nil; -} - @end #if TARGET_OS_IOS @implementation NSURL (ASPhotosFrameworkURLs) diff --git a/AsyncDisplayKit/ASNetworkImageNode.h b/AsyncDisplayKit/ASNetworkImageNode.h index be08fa2158..82513a8c55 100644 --- a/AsyncDisplayKit/ASNetworkImageNode.h +++ b/AsyncDisplayKit/ASNetworkImageNode.h @@ -45,19 +45,19 @@ NS_ASSUME_NONNULL_BEGIN /** * The delegate, which must conform to the protocol. */ -@property (nonatomic, weak, readwrite) id delegate; +@property (atomic, weak, readwrite) id delegate; /** * 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. * * @discussion Changing this property will reset the displayed image to a placeholder () while loading. */ -@property (nullable, nonatomic, strong, readwrite) NSURL *URL; +@property (nullable, atomic, strong, readwrite) NSURL *URL; /** * Download and display a new image. diff --git a/AsyncDisplayKit/ASNetworkImageNode.mm b/AsyncDisplayKit/ASNetworkImageNode.mm index ee350ef0e8..c91f3b2960 100755 --- a/AsyncDisplayKit/ASNetworkImageNode.mm +++ b/AsyncDisplayKit/ASNetworkImageNode.mm @@ -21,8 +21,8 @@ @interface ASNetworkImageNode () { ASDN::RecursiveMutex _lock; - __weak id _cache; - __weak id _downloader; + __weak id _cache; + __weak id _downloader; // Only access any of these with _lock. __weak id _delegate; @@ -39,7 +39,8 @@ BOOL _downloaderSupportsNewProtocol; BOOL _downloaderImplementsSetProgress; BOOL _downloaderImplementsSetPriority; - BOOL _cacherSupportsNewProtocol; + BOOL _cacheSupportsNewProtocol; + BOOL _cacheSupportsClearing; } @end @@ -53,16 +54,17 @@ _cache = cache; _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; - _downloaderImplementsSetPriority = [downloader respondsToSelector:@selector(setPriority:withDownloadIdentifier:)] ? YES : NO; + _downloaderImplementsSetProgress = [downloader respondsToSelector:@selector(setProgressImageBlock:callbackQueue:withDownloadIdentifier:)]; + _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; self.shouldBypassEnsureDisplay = YES; @@ -150,44 +152,60 @@ return _delegate; } +/* displayWillStart in ASMultiplexImageNode has a very similar implementation. Changes here are likely necessary + in ASMultiplexImageNode as well. */ - (void)displayWillStart { [super displayWillStart]; [self fetchData]; - if (self.image == nil) { - if (_downloaderImplementsSetPriority) { - { - ASDN::MutexLocker l(_lock); - if (_downloadIdentifier != nil) { - [_downloader setPriority:ASImageDownloaderPriorityDisplay withDownloadIdentifier:_downloadIdentifier]; - } + if (self.image == nil && _downloaderImplementsSetPriority) { + ASDN::MutexLocker l(_lock); + if (_downloadIdentifier != nil) { + [_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) { + ASDN::MutexLocker l(_lock); - if (_downloaderImplementsSetProgress) { - { - ASDN::MutexLocker l(_lock); - - if (_downloadIdentifier != nil) { - __weak __typeof__(self) weakSelf = self; - [_downloader setProgressImageBlock:^(UIImage * _Nonnull progressImage, id _Nullable downloadIdentifier) { - __typeof__(self) strongSelf = weakSelf; - if (strongSelf == nil) { - return; - } - - ASDN::MutexLocker l(_lock); - //Getting a result back for a different download identifier, download must not have been successfully canceled - if (![strongSelf->_downloadIdentifier isEqual:downloadIdentifier] && downloadIdentifier != nil) { - return; - } - - strongSelf.image = progressImage; - } callbackQueue:dispatch_get_main_queue() withDownloadIdentifier:_downloadIdentifier]; - } + if (_downloadIdentifier != nil) { + __weak __typeof__(self) weakSelf = self; + ASImageDownloaderProgressImage progress = nil; + if (isVisible) { + progress = ^(UIImage * _Nonnull progressImage, id _Nullable downloadIdentifier) { + __typeof__(self) strongSelf = weakSelf; + if (strongSelf == nil) { + return; + } + + ASDN::MutexLocker l(_lock); + //Getting a result back for a different download identifier, download must not have been successfully canceled + if (ASObjectIsEqual(strongSelf->_downloadIdentifier, downloadIdentifier) == NO && downloadIdentifier != nil) { + return; + } + + strongSelf.image = progressImage; + }; } + [_downloader setProgressImageBlock:progress callbackQueue:dispatch_get_main_queue() withDownloadIdentifier:_downloadIdentifier]; } } } @@ -202,6 +220,9 @@ [self _cancelImageDownload]; self.image = _defaultImage; _imageLoaded = NO; + if (_cacheSupportsClearing) { + [_cache clearFetchedImageFromCacheWithURL:_URL]; + } } } @@ -294,7 +315,7 @@ ASDN::MutexLocker l(strongSelf->_lock); //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; } @@ -333,18 +354,16 @@ } }; - if (_cacherSupportsNewProtocol) { + if (_cacheSupportsNewProtocol) { [_cache cachedImageWithURL:_URL callbackQueue:dispatch_get_main_queue() completion:cacheCompletion]; } else { - void (^oldCacheCompletion)(CGImageRef) = ^(CGImageRef image) { - cacheCompletion([UIImage imageWithCGImage:image]); - }; - [_cache fetchCachedImageWithURL:_URL callbackQueue:dispatch_get_main_queue() - completion:oldCacheCompletion]; + completion:^(CGImageRef image) { + cacheCompletion([UIImage imageWithCGImage:image]); + }]; } } else { [self _downloadImageWithCompletion:finished]; diff --git a/AsyncDisplayKit/Details/ASImageProtocols.h b/AsyncDisplayKit/Details/ASImageProtocols.h index 4f1abd65e6..eb3690023f 100644 --- a/AsyncDisplayKit/Details/ASImageProtocols.h +++ b/AsyncDisplayKit/Details/ASImageProtocols.h @@ -16,12 +16,6 @@ typedef void(^ASImageCacherCompletion)(UIImage * _Nullable imageFromCache); @protocol 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; /** @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 the calling thread as it is likely to be called from the main thread. */ -- (void)cachedImageWithURL:(nullable NSURL *)URL - callbackQueue:(nullable dispatch_queue_t)callbackQueue +- (void)cachedImageWithURL:(NSURL *)URL + callbackQueue:(dispatch_queue_t)callbackQueue 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 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 NS_ENUM(NSUInteger, ASImageDownloaderPriority) { - ASImageDownloaderPriorityNormal = 0, - ASImageDownloaderPriorityDisplay, + ASImageDownloaderPriorityPreload = 0, + ASImageDownloaderPriorityImminent, + ASImageDownloaderPriorityVisible }; @protocol ASImageDownloaderProtocol @@ -62,15 +64,7 @@ typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) { @optional -//You must implement one of the two following methods - -/** - @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; +//You must implement the following method OR the deprecated method at the bottom /** @abstract Downloads an image with the given URL. @@ -113,4 +107,29 @@ withDownloadIdentifier:(id)downloadIdentifier; @end +@protocol ASImageDownloaderProtocolDeprecated + +@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 + +@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 diff --git a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m index d88bbea19f..0345981298 100644 --- a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m +++ b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m @@ -8,6 +8,9 @@ #ifdef PIN_REMOTE_IMAGE #import "ASPINRemoteImageDownloader.h" + +#import "ASAssert.h" + #import #import @@ -29,28 +32,18 @@ callbackQueue:(dispatch_queue_t)callbackQueue completion:(void (^)(CGImageRef imageFromCache))completion { - NSString *key = [[PINRemoteImageManager sharedImageManager] cacheKeyForURL:URL processorKey:nil]; - UIImage *image = [[[[PINRemoteImageManager sharedImageManager] cache] memoryCache] objectForKey:key]; - + //We do not check the cache here and instead check it in downloadImageWithURL to avoid checking the cache twice. dispatch_async(callbackQueue, ^{ - completion([image CGImage]); + completion(nil); }); } -/** - @abstract Downloads an image with the given URL. - @param URL The URL of the image to download. - @param callbackQueue The queue to call `downloadProgressBlock` and `completion` on. If this value is nil, both blocks - 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. - */ +- (void)clearFetchedImageFromCacheWithURL:(NSURL *)URL +{ + NSString *key = [[PINRemoteImageManager sharedImageManager] cacheKeyForURL:URL processorKey:nil]; + [[[[PINRemoteImageManager sharedImageManager] cache] memoryCache] removeObjectForKey:key]; +} + - (nullable id)downloadImageWithURL:(NSURL *)URL callbackQueue:(dispatch_queue_t)callbackQueue 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 { - NSAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID"); + ASDisplayNodeAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID"); [[PINRemoteImageManager sharedImageManager] cancelTaskWithUUID: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) { dispatch_async(callbackQueue, ^{ @@ -88,9 +75,23 @@ - (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