diff --git a/AsyncDisplayKit/ASMultiplexImageNode.h b/AsyncDisplayKit/ASMultiplexImageNode.h index eb01209dfd..6780a3513d 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.h +++ b/AsyncDisplayKit/ASMultiplexImageNode.h @@ -130,7 +130,7 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { * @see `+[NSURL URLWithAssetLocalIdentifier:targetSize:contentMode:options:]` below. */ -@property (nonatomic, strong) PHImageManager *imageManager; +@property (nullable, nonatomic, strong) PHImageManager *imageManager; #endif @end diff --git a/AsyncDisplayKit/Details/ASImageProtocols.h b/AsyncDisplayKit/Details/ASImageProtocols.h index 6b86fb97db..ff6803bd8d 100644 --- a/AsyncDisplayKit/Details/ASImageProtocols.h +++ b/AsyncDisplayKit/Details/ASImageProtocols.h @@ -61,7 +61,16 @@ typedef void(^ASImageCacherCompletion)(id _Nullable i @end +/** + @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. + @param downloadIdentifier The identifier for the download task that completed. + */ typedef void(^ASImageDownloaderCompletion)(id _Nullable image, NSError * _Nullable error, id _Nullable downloadIdentifier); + +/** + @param progress The progress of the download, in the range of (0.0, 1.0), inclusive. + */ typedef void(^ASImageDownloaderProgress)(CGFloat progress); typedef void(^ASImageDownloaderProgressImage)(UIImage *progressImage, CGFloat progress, id _Nullable downloadIdentifier); @@ -98,10 +107,7 @@ typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) { @param URL The URL of the image to download. @param callbackQueue The queue to call `downloadProgressBlock` and `completion` on. @param downloadProgress 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. @@ -109,7 +115,7 @@ typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) { - (nullable id)downloadImageWithURL:(NSURL *)URL callbackQueue:(dispatch_queue_t)callbackQueue downloadProgress:(nullable ASImageDownloaderProgress)downloadProgress - completion:(nullable ASImageDownloaderCompletion)completion; + completion:(ASImageDownloaderCompletion)completion; /** diff --git a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.h b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.h index 12c6b27376..a1238272ed 100644 --- a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.h +++ b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.h @@ -9,8 +9,12 @@ #import #import "ASImageProtocols.h" +NS_ASSUME_NONNULL_BEGIN + @interface ASPINRemoteImageDownloader : NSObject -+ (instancetype)sharedDownloader; ++ (ASPINRemoteImageDownloader *)sharedDownloader; @end + +NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m index 401211709c..ee78b0e7b6 100644 --- a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m +++ b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m @@ -96,8 +96,9 @@ - (id )synchronouslyFetchedCachedImageWithURL:(NSURL *)URL; { - NSString *key = [[self sharedPINRemoteImageManager] cacheKeyForURL:URL processorKey:nil]; - PINRemoteImageManagerResult *result = [[self sharedPINRemoteImageManager] synchronousImageFromCacheWithCacheKey:key options:PINRemoteImageManagerDownloadOptionsSkipDecode]; + PINRemoteImageManager *manager = [self sharedPINRemoteImageManager]; + NSString *key = [manager cacheKeyForURL:URL processorKey:nil]; + PINRemoteImageManagerResult *result = [manager synchronousImageFromCacheWithCacheKey:key options:PINRemoteImageManagerDownloadOptionsSkipDecode]; #if PIN_ANIMATED_AVAILABLE if (result.alternativeRepresentation) { return result.alternativeRepresentation; @@ -133,7 +134,18 @@ downloadProgress:(ASImageDownloaderProgress)downloadProgress completion:(ASImageDownloaderCompletion)completion; { - return [[self sharedPINRemoteImageManager] downloadImageWithURL:URL options:PINRemoteImageManagerDownloadOptionsSkipDecode completion:^(PINRemoteImageManagerResult *result) { + return [[self sharedPINRemoteImageManager] downloadImageWithURL:URL options:PINRemoteImageManagerDownloadOptionsSkipDecode progressDownload:^(int64_t completedBytes, int64_t totalBytes) { + if (downloadProgress == nil) { return; } + + /// If we're targeting the main queue and we're on the main thread, call immediately. + if (ASDisplayNodeThreadIsMain() && callbackQueue == dispatch_get_main_queue()) { + downloadProgress(totalBytes / (CGFloat)completedBytes); + } else { + dispatch_async(callbackQueue, ^{ + downloadProgress(totalBytes / (CGFloat)completedBytes); + }); + } + } completion:^(PINRemoteImageManagerResult * _Nonnull result) { /// If we're targeting the main queue and we're on the main thread, complete immediately. if (ASDisplayNodeThreadIsMain() && callbackQueue == dispatch_get_main_queue()) { #if PIN_ANIMATED_AVAILABLE