From af61645fafc4e0e0ae2df90d3edca4f4795a1812 Mon Sep 17 00:00:00 2001 From: Garrett Moon Date: Fri, 11 Mar 2016 15:51:17 -0800 Subject: [PATCH] Add support for attempting to get image synchronously --- AsyncDisplayKit/ASNetworkImageNode.mm | 15 +++++++++++++++ AsyncDisplayKit/Details/ASImageProtocols.h | 13 +++++++++++++ .../Details/ASPINRemoteImageDownloader.m | 7 +++++++ 3 files changed, 35 insertions(+) diff --git a/AsyncDisplayKit/ASNetworkImageNode.mm b/AsyncDisplayKit/ASNetworkImageNode.mm index e1b2210760..c7cadff233 100755 --- a/AsyncDisplayKit/ASNetworkImageNode.mm +++ b/AsyncDisplayKit/ASNetworkImageNode.mm @@ -49,6 +49,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0}; BOOL _cacheSupportsNewProtocol; BOOL _cacheSupportsClearing; + BOOL _cacheSupportsSynchronousFetch; } @end @@ -73,6 +74,7 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0}; _cacheSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)]; _cacheSupportsClearing = [cache respondsToSelector:@selector(clearFetchedImageFromCacheWithURL:)]; + _cacheSupportsSynchronousFetch = [cache respondsToSelector:@selector(synchronouslyFetchedCachedImageWithURL:)]; _shouldCacheImage = YES; self.shouldBypassEnsureDisplay = YES; @@ -169,6 +171,19 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0}; - (void)displayWillStart { [super displayWillStart]; + + if (_cacheSupportsSynchronousFetch) { + { + ASDN::MutexLocker l(_lock); + if (_URL && _downloadIdentifier == nil) { + UIImage *result = [_cache synchronouslyFetchedCachedImageWithURL:_URL]; + if (result) { + self.image = result; + _imageLoaded = YES; + } + } + } + } [self fetchData]; diff --git a/AsyncDisplayKit/Details/ASImageProtocols.h b/AsyncDisplayKit/Details/ASImageProtocols.h index ddbccb0eb1..365c374a00 100644 --- a/AsyncDisplayKit/Details/ASImageProtocols.h +++ b/AsyncDisplayKit/Details/ASImageProtocols.h @@ -17,6 +17,19 @@ typedef void(^ASImageCacherCompletion)(UIImage * _Nullable imageFromCache); @optional +/** + @abstract Attempts to fetch an image with the given URL from a memory cache. + @param URL The URL of the image to retrieve from the cache. + @discussion This method exists to support synchronous rendering of nodes. Before the layer is drawn, this method + is called to attempt to get the image out of the cache synchronously. This allows drawing to occur on the main thread + if displaysAsynchronously is set to NO or recursivelyEnsureDisplaySynchronously: has been called. + + If `URL` is nil, `completion` will be invoked immediately with a nil image. This method *should* block + the calling thread to fetch the image from a fast memory cache. It is OK to return nil from this method and instead + support only cachedImageWithURL:callbackQueue:completion: however, synchronous rendering will not be possible. + */ +- (_Nullable UIImage *)synchronouslyFetchedCachedImageWithURL:(NSURL *)URL; + /** @abstract Attempts to fetch an image with the given URL from the cache. @param URL The URL of the image to retrieve from the cache. diff --git a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m index dc15fb98ec..13f304f76e 100644 --- a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m +++ b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m @@ -29,6 +29,13 @@ #pragma mark ASImageProtocols +- (UIImage *)synchronouslyFetchedCachedImageWithURL:(NSURL *)URL +{ + NSString *key = [[PINRemoteImageManager sharedImageManager] cacheKeyForURL:URL processorKey:nil]; + PINRemoteImageManagerResult *result = [[PINRemoteImageManager sharedImageManager] synchronousImageFromCacheWithCacheKey:key options:PINRemoteImageManagerDownloadOptionsSkipDecode]; + return result.image; +} + - (void)fetchCachedImageWithURL:(NSURL *)URL callbackQueue:(dispatch_queue_t)callbackQueue completion:(void (^)(CGImageRef imageFromCache))completion