mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Add default PINRemoteImageDownloader
This commit is contained in:
@@ -37,6 +37,9 @@ Pod::Spec.new do |spec|
|
|||||||
'AsyncDisplayKit/Details/ASDealloc2MainObject.h',
|
'AsyncDisplayKit/Details/ASDealloc2MainObject.h',
|
||||||
'AsyncDisplayKit/Details/ASDealloc2MainObject.m',
|
'AsyncDisplayKit/Details/ASDealloc2MainObject.m',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
#Subspecs
|
||||||
|
|
||||||
spec.subspec 'ASDealloc2MainObject' do |mrr|
|
spec.subspec 'ASDealloc2MainObject' do |mrr|
|
||||||
mrr.requires_arc = false
|
mrr.requires_arc = false
|
||||||
mrr.source_files = [
|
mrr.source_files = [
|
||||||
@@ -45,6 +48,15 @@ Pod::Spec.new do |spec|
|
|||||||
'AsyncDisplayKit/Details/ASDealloc2MainObject.m',
|
'AsyncDisplayKit/Details/ASDealloc2MainObject.m',
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
spec.subspec 'PINRemoteImage' do |pin|
|
||||||
|
pin.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_REMOTE_IMAGE=1' }
|
||||||
|
pin.dependency 'PINRemoteImage'
|
||||||
|
pin.dependency 'AsyncDisplayKit/ASDealloc2MainObject'
|
||||||
|
end
|
||||||
|
|
||||||
|
# Include optional FLAnimatedImage module
|
||||||
|
spec.default_subspec = 'PINRemoteImage'
|
||||||
|
|
||||||
spec.social_media_url = 'https://twitter.com/fbOpenSource'
|
spec.social_media_url = 'https://twitter.com/fbOpenSource'
|
||||||
spec.library = 'c++'
|
spec.library = 'c++'
|
||||||
|
|||||||
@@ -26,6 +26,12 @@
|
|||||||
#error ASMultiplexImageNode can be used on iOS 7, but must be linked against the iOS 8 SDK.
|
#error ASMultiplexImageNode can be used on iOS 7, but must be linked against the iOS 8 SDK.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PIN_REMOTE_IMAGE
|
||||||
|
#import "ASPINRemoteImageDownloader.h"
|
||||||
|
#else
|
||||||
|
#import "ASBasicImageDownloader.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
NSString *const ASMultiplexImageNodeErrorDomain = @"ASMultiplexImageNodeErrorDomain";
|
NSString *const ASMultiplexImageNodeErrorDomain = @"ASMultiplexImageNodeErrorDomain";
|
||||||
|
|
||||||
static NSString *const kAssetsLibraryURLScheme = @"assets-library";
|
static NSString *const kAssetsLibraryURLScheme = @"assets-library";
|
||||||
@@ -72,7 +78,14 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
__weak NSOperation *_phImageRequestOperation;
|
__weak NSOperation *_phImageRequestOperation;
|
||||||
|
|
||||||
// Networking.
|
// Networking.
|
||||||
|
ASDN::Mutex _downloadIdentifierLock;
|
||||||
id _downloadIdentifier;
|
id _downloadIdentifier;
|
||||||
|
|
||||||
|
//set on init only
|
||||||
|
BOOL _downloaderSupportsNewProtocol;
|
||||||
|
BOOL _downloaderImplementsSetProgress;
|
||||||
|
BOOL _downloaderImplementsSetPriority;
|
||||||
|
BOOL _cacherSupportsNewProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! @abstract Read-write redeclaration of property declared in ASMultiplexImageNode.h.
|
//! @abstract Read-write redeclaration of property declared in ASMultiplexImageNode.h.
|
||||||
@@ -162,6 +175,18 @@ 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:.");
|
||||||
|
|
||||||
|
_downloaderSupportsNewProtocol = [downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgress:completion:)] ? YES : NO;
|
||||||
|
|
||||||
|
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:");
|
||||||
|
|
||||||
|
_downloaderImplementsSetProgress = [downloader respondsToSelector:@selector(setProgressImageBlock:callbackQueue:withDownloadIdentifier:)] ? YES : NO;
|
||||||
|
_downloaderImplementsSetPriority = [downloader respondsToSelector:@selector(setPriority:withDownloadIdentifier:)] ? YES : NO;
|
||||||
|
|
||||||
|
_cacherSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)] ? YES : NO;
|
||||||
|
|
||||||
self.shouldBypassEnsureDisplay = YES;
|
self.shouldBypassEnsureDisplay = YES;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -169,8 +194,11 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
|
|
||||||
- (instancetype)init
|
- (instancetype)init
|
||||||
{
|
{
|
||||||
ASDISPLAYNODE_NOT_DESIGNATED_INITIALIZER();
|
#if PIN_REMOTE_IMAGE
|
||||||
return [self initWithCache:nil downloader:nil]; // satisfy compiler
|
return [self initWithCache:[ASPINRemoteImageDownloader sharedDownloader] downloader:[ASPINRemoteImageDownloader sharedDownloader]];
|
||||||
|
#else
|
||||||
|
return [self initWithCache:nil downloader:[ASBasicImageDownloader sharedImageDownloader]];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
@@ -238,6 +266,48 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)displayWillStart
|
||||||
|
{
|
||||||
|
[super displayWillStart];
|
||||||
|
|
||||||
|
[self fetchData];
|
||||||
|
|
||||||
|
if (_downloaderImplementsSetPriority) {
|
||||||
|
{
|
||||||
|
ASDN::MutexLocker l(_downloadIdentifierLock);
|
||||||
|
if (_downloadIdentifier != nil) {
|
||||||
|
[_downloader setPriority:ASImageDownloaderPriorityDisplay 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark - Core
|
#pragma mark - Core
|
||||||
|
|
||||||
- (void)setDelegate:(id <ASMultiplexImageNodeDelegate>)delegate
|
- (void)setDelegate:(id <ASMultiplexImageNodeDelegate>)delegate
|
||||||
@@ -331,10 +401,13 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
|
|
||||||
- (void)_setDownloadIdentifier:(id)downloadIdentifier
|
- (void)_setDownloadIdentifier:(id)downloadIdentifier
|
||||||
{
|
{
|
||||||
|
ASDN::MutexLocker l(_downloadIdentifierLock);
|
||||||
if (ASObjectIsEqual(downloadIdentifier, _downloadIdentifier))
|
if (ASObjectIsEqual(downloadIdentifier, _downloadIdentifier))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[_downloader cancelImageDownloadForIdentifier:_downloadIdentifier];
|
if (_downloadIdentifier) {
|
||||||
|
[_downloader cancelImageDownloadForIdentifier:_downloadIdentifier];
|
||||||
|
}
|
||||||
_downloadIdentifier = downloadIdentifier;
|
_downloadIdentifier = downloadIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,10 +695,16 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
ASDisplayNodeAssertNotNil(completionBlock, @"completionBlock is required");
|
ASDisplayNodeAssertNotNil(completionBlock, @"completionBlock is required");
|
||||||
|
|
||||||
if (_cache) {
|
if (_cache) {
|
||||||
[_cache fetchCachedImageWithURL:imageURL callbackQueue:dispatch_get_main_queue() completion:^(CGImageRef coreGraphicsImageFromCache) {
|
if (_cacherSupportsNewProtocol) {
|
||||||
UIImage *imageFromCache = (coreGraphicsImageFromCache ? [UIImage imageWithCGImage:coreGraphicsImageFromCache] : nil);
|
[_cache cachedImageWithURL:imageURL callbackQueue:dispatch_get_main_queue() completion:^(UIImage *imageFromCache) {
|
||||||
completionBlock(imageFromCache);
|
completionBlock(imageFromCache);
|
||||||
}];
|
}];
|
||||||
|
} else {
|
||||||
|
[_cache fetchCachedImageWithURL:imageURL callbackQueue:dispatch_get_main_queue() completion:^(CGImageRef coreGraphicsImageFromCache) {
|
||||||
|
UIImage *imageFromCache = (coreGraphicsImageFromCache ? [UIImage imageWithCGImage:coreGraphicsImageFromCache] : nil);
|
||||||
|
completionBlock(imageFromCache);
|
||||||
|
}];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// If we don't have a cache, just fail immediately.
|
// If we don't have a cache, just fail immediately.
|
||||||
else {
|
else {
|
||||||
@@ -655,22 +734,46 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Download!
|
// Download!
|
||||||
[self _setDownloadIdentifier:[_downloader downloadImageWithURL:imageURL
|
if (_downloaderSupportsNewProtocol) {
|
||||||
callbackQueue:dispatch_get_main_queue()
|
[self _setDownloadIdentifier:[_downloader downloadImageWithURL:imageURL
|
||||||
downloadProgressBlock:downloadProgressBlock
|
callbackQueue:dispatch_get_main_queue()
|
||||||
completion:^(CGImageRef coreGraphicsImage, NSError *error) {
|
downloadProgress:downloadProgressBlock
|
||||||
// We dereference iVars directly, so we can't have weakSelf going nil on us.
|
completion:^(UIImage *downloadedImage, NSError *error, id downloadIdentifier) {
|
||||||
__typeof__(self) strongSelf = weakSelf;
|
// We dereference iVars directly, so we can't have weakSelf going nil on us.
|
||||||
if (!strongSelf)
|
__typeof__(self) strongSelf = weakSelf;
|
||||||
return;
|
if (!strongSelf)
|
||||||
|
return;
|
||||||
UIImage *downloadedImage = (coreGraphicsImage ? [UIImage imageWithCGImage:coreGraphicsImage] : nil);
|
|
||||||
completionBlock(downloadedImage, error);
|
ASDN::MutexLocker l(_downloadIdentifierLock);
|
||||||
|
//Getting a result back for a different download identifier, download must not have been successfully canceled
|
||||||
// Delegateify.
|
if (![_downloadIdentifier isEqual:downloadIdentifier] && downloadIdentifier != nil) {
|
||||||
if (strongSelf->_delegateFlags.downloadFinish)
|
return;
|
||||||
[strongSelf->_delegate multiplexImageNode:weakSelf didFinishDownloadingImageWithIdentifier:imageIdentifier error:error];
|
}
|
||||||
}]];
|
|
||||||
|
completionBlock(downloadedImage, error);
|
||||||
|
|
||||||
|
// Delegateify.
|
||||||
|
if (strongSelf->_delegateFlags.downloadFinish)
|
||||||
|
[strongSelf->_delegate multiplexImageNode:weakSelf didFinishDownloadingImageWithIdentifier:imageIdentifier error:error];
|
||||||
|
}]];
|
||||||
|
} else {
|
||||||
|
[self _setDownloadIdentifier:[_downloader downloadImageWithURL:imageURL
|
||||||
|
callbackQueue:dispatch_get_main_queue()
|
||||||
|
downloadProgressBlock:downloadProgressBlock
|
||||||
|
completion:^(CGImageRef coreGraphicsImage, NSError *error) {
|
||||||
|
// We dereference iVars directly, so we can't have weakSelf going nil on us.
|
||||||
|
__typeof__(self) strongSelf = weakSelf;
|
||||||
|
if (!strongSelf)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UIImage *downloadedImage = (coreGraphicsImage ? [UIImage imageWithCGImage:coreGraphicsImage] : nil);
|
||||||
|
completionBlock(downloadedImage, error);
|
||||||
|
|
||||||
|
// Delegateify.
|
||||||
|
if (strongSelf->_delegateFlags.downloadFinish)
|
||||||
|
[strongSelf->_delegate multiplexImageNode:weakSelf didFinishDownloadingImageWithIdentifier:imageIdentifier error:error];
|
||||||
|
}]];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|||||||
@@ -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 (atomic, weak, readwrite) id<ASNetworkImageNodeDelegate> delegate;
|
@property (nonatomic, 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, atomic, strong, readwrite) UIImage *defaultImage;
|
@property (nullable, nonatomic, 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, atomic, strong, readwrite) NSURL *URL;
|
@property (nullable, nonatomic, strong, readwrite) NSURL *URL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download and display a new image.
|
* Download and display a new image.
|
||||||
|
|||||||
@@ -14,6 +14,10 @@
|
|||||||
#import "ASEqualityHelpers.h"
|
#import "ASEqualityHelpers.h"
|
||||||
#import "ASThread.h"
|
#import "ASThread.h"
|
||||||
|
|
||||||
|
#if PIN_REMOTE_IMAGE
|
||||||
|
#import "ASPINRemoteImageDownloader.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
@interface ASNetworkImageNode ()
|
@interface ASNetworkImageNode ()
|
||||||
{
|
{
|
||||||
ASDN::RecursiveMutex _lock;
|
ASDN::RecursiveMutex _lock;
|
||||||
@@ -27,9 +31,15 @@
|
|||||||
UIImage *_defaultImage;
|
UIImage *_defaultImage;
|
||||||
|
|
||||||
NSUUID *_cacheUUID;
|
NSUUID *_cacheUUID;
|
||||||
id _imageDownload;
|
id _downloadIdentifier;
|
||||||
|
|
||||||
BOOL _imageLoaded;
|
BOOL _imageLoaded;
|
||||||
|
|
||||||
|
//set on init only
|
||||||
|
BOOL _downloaderSupportsNewProtocol;
|
||||||
|
BOOL _downloaderImplementsSetProgress;
|
||||||
|
BOOL _downloaderImplementsSetPriority;
|
||||||
|
BOOL _cacherSupportsNewProtocol;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -42,6 +52,18 @@
|
|||||||
|
|
||||||
_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:.");
|
||||||
|
|
||||||
|
_downloaderSupportsNewProtocol = [downloader respondsToSelector:@selector(downloadImageWithURL:callbackQueue:downloadProgress:completion:)] ? YES : NO;
|
||||||
|
|
||||||
|
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:");
|
||||||
|
|
||||||
|
_downloaderImplementsSetProgress = [downloader respondsToSelector:@selector(setProgressImageBlock:callbackQueue:withDownloadIdentifier:)] ? YES : NO;
|
||||||
|
_downloaderImplementsSetPriority = [downloader respondsToSelector:@selector(setPriority:withDownloadIdentifier:)] ? YES : NO;
|
||||||
|
|
||||||
|
_cacherSupportsNewProtocol = [cache respondsToSelector:@selector(cachedImageWithURL:callbackQueue:completion:)] ? YES : NO;
|
||||||
|
|
||||||
_shouldCacheImage = YES;
|
_shouldCacheImage = YES;
|
||||||
self.shouldBypassEnsureDisplay = YES;
|
self.shouldBypassEnsureDisplay = YES;
|
||||||
|
|
||||||
@@ -50,7 +72,11 @@
|
|||||||
|
|
||||||
- (instancetype)init
|
- (instancetype)init
|
||||||
{
|
{
|
||||||
|
#if PIN_REMOTE_IMAGE
|
||||||
|
return [self initWithCache:[ASPINRemoteImageDownloader sharedDownloader] downloader:[ASPINRemoteImageDownloader sharedDownloader]];
|
||||||
|
#else
|
||||||
return [self initWithCache:nil downloader:[ASBasicImageDownloader sharedImageDownloader]];
|
return [self initWithCache:nil downloader:[ASBasicImageDownloader sharedImageDownloader]];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
@@ -129,6 +155,41 @@
|
|||||||
[super displayWillStart];
|
[super displayWillStart];
|
||||||
|
|
||||||
[self fetchData];
|
[self fetchData];
|
||||||
|
|
||||||
|
if (self.image == nil) {
|
||||||
|
if (_downloaderImplementsSetPriority) {
|
||||||
|
{
|
||||||
|
ASDN::MutexLocker l(_lock);
|
||||||
|
if (_downloadIdentifier != nil) {
|
||||||
|
[_downloader setPriority:ASImageDownloaderPriorityDisplay withDownloadIdentifier:_downloadIdentifier];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)clearFetchedData
|
- (void)clearFetchedData
|
||||||
@@ -158,31 +219,44 @@
|
|||||||
|
|
||||||
- (void)_cancelImageDownload
|
- (void)_cancelImageDownload
|
||||||
{
|
{
|
||||||
if (!_imageDownload) {
|
if (!_downloadIdentifier) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[_downloader cancelImageDownloadForIdentifier:_imageDownload];
|
if (_downloadIdentifier) {
|
||||||
_imageDownload = nil;
|
[_downloader cancelImageDownloadForIdentifier:_downloadIdentifier];
|
||||||
|
}
|
||||||
|
_downloadIdentifier = nil;
|
||||||
|
|
||||||
_cacheUUID = nil;
|
_cacheUUID = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_downloadImageWithCompletion:(void (^)(CGImageRef, NSError*))finished
|
- (void)_downloadImageWithCompletion:(void (^)(UIImage *image, NSError*, id downloadIdentifier))finished
|
||||||
{
|
{
|
||||||
_imageDownload = [_downloader downloadImageWithURL:_URL
|
if (_downloaderSupportsNewProtocol) {
|
||||||
callbackQueue:dispatch_get_main_queue()
|
_downloadIdentifier = [_downloader downloadImageWithURL:_URL
|
||||||
downloadProgressBlock:NULL
|
callbackQueue:dispatch_get_main_queue()
|
||||||
completion:^(CGImageRef responseImage, NSError *error) {
|
downloadProgress:NULL
|
||||||
if (finished != NULL) {
|
completion:^(UIImage * _Nullable image, NSError * _Nullable error, id _Nullable downloadIdentifier) {
|
||||||
finished(responseImage, error);
|
if (finished != NULL) {
|
||||||
}
|
finished(image, error, downloadIdentifier);
|
||||||
}];
|
}
|
||||||
|
}];
|
||||||
|
} else {
|
||||||
|
_downloadIdentifier = [_downloader downloadImageWithURL:_URL
|
||||||
|
callbackQueue:dispatch_get_main_queue()
|
||||||
|
downloadProgressBlock:NULL
|
||||||
|
completion:^(CGImageRef responseImage, NSError *error) {
|
||||||
|
if (finished != NULL) {
|
||||||
|
finished([UIImage imageWithCGImage:responseImage], error, nil);
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_lazilyLoadImageIfNecessary
|
- (void)_lazilyLoadImageIfNecessary
|
||||||
{
|
{
|
||||||
if (!_imageLoaded && _URL != nil && _imageDownload == nil) {
|
if (!_imageLoaded && _URL != nil && _downloadIdentifier == nil) {
|
||||||
if (_URL.isFileURL) {
|
if (_URL.isFileURL) {
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(_lock);
|
ASDN::MutexLocker l(_lock);
|
||||||
@@ -210,7 +284,7 @@
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
__weak __typeof__(self) weakSelf = self;
|
__weak __typeof__(self) weakSelf = self;
|
||||||
void (^finished)(CGImageRef, NSError *) = ^(CGImageRef responseImage, NSError *error) {
|
void (^finished)(UIImage *, NSError *, id downloadIdentifier) = ^(UIImage *responseImage, NSError *error, id downloadIdentifier) {
|
||||||
__typeof__(self) strongSelf = weakSelf;
|
__typeof__(self) strongSelf = weakSelf;
|
||||||
if (strongSelf == nil) {
|
if (strongSelf == nil) {
|
||||||
return;
|
return;
|
||||||
@@ -218,13 +292,18 @@
|
|||||||
|
|
||||||
{
|
{
|
||||||
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
|
||||||
|
if (![strongSelf->_downloadIdentifier isEqual:downloadIdentifier] && downloadIdentifier != nil) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (responseImage != NULL) {
|
if (responseImage != NULL) {
|
||||||
strongSelf->_imageLoaded = YES;
|
strongSelf->_imageLoaded = YES;
|
||||||
strongSelf.image = [UIImage imageWithCGImage:responseImage];
|
strongSelf.image = responseImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf->_imageDownload = nil;
|
strongSelf->_downloadIdentifier = nil;
|
||||||
|
|
||||||
strongSelf->_cacheUUID = nil;
|
strongSelf->_cacheUUID = nil;
|
||||||
}
|
}
|
||||||
@@ -241,22 +320,32 @@
|
|||||||
NSUUID *cacheUUID = [NSUUID UUID];
|
NSUUID *cacheUUID = [NSUUID UUID];
|
||||||
_cacheUUID = cacheUUID;
|
_cacheUUID = cacheUUID;
|
||||||
|
|
||||||
void (^cacheCompletion)(CGImageRef) = ^(CGImageRef image) {
|
void (^cacheCompletion)(UIImage *) = ^(UIImage *image) {
|
||||||
// If the cache UUID changed, that means this request was cancelled.
|
// If the cache UUID changed, that means this request was cancelled.
|
||||||
if (![_cacheUUID isEqual:cacheUUID]) {
|
if (![_cacheUUID isEqual:cacheUUID]) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image == NULL && _downloader != nil) {
|
if (image == NULL && _downloader != nil) {
|
||||||
[self _downloadImageWithCompletion:finished];
|
[self _downloadImageWithCompletion:finished];
|
||||||
} else {
|
} else {
|
||||||
finished(image, NULL);
|
finished(image, NULL, nil);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
[_cache fetchCachedImageWithURL:_URL
|
if (_cacherSupportsNewProtocol) {
|
||||||
callbackQueue:dispatch_get_main_queue()
|
[_cache cachedImageWithURL:_URL
|
||||||
completion:cacheCompletion];
|
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];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
[self _downloadImageWithCompletion:finished];
|
[self _downloadImageWithCompletion:finished];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ static const char *kContextKey = NSStringFromClass(ASBasicImageDownloaderContext
|
|||||||
|
|
||||||
- (id)downloadImageWithURL:(NSURL *)URL
|
- (id)downloadImageWithURL:(NSURL *)URL
|
||||||
callbackQueue:(dispatch_queue_t)callbackQueue
|
callbackQueue:(dispatch_queue_t)callbackQueue
|
||||||
downloadProgressBlock:(void (^)(CGFloat))downloadProgressBlock
|
downloadProgress:(void (^)(CGFloat))downloadProgressBlock
|
||||||
completion:(void (^)(CGImageRef, NSError *))completion
|
completion:(void (^)(CGImageRef, NSError *))completion
|
||||||
{
|
{
|
||||||
ASBasicImageDownloaderContext *context = [ASBasicImageDownloaderContext contextForURL:URL];
|
ASBasicImageDownloaderContext *context = [ASBasicImageDownloaderContext contextForURL:URL];
|
||||||
|
|||||||
@@ -6,51 +6,51 @@
|
|||||||
* of patent rights can be found in the PATENTS file in the same directory.
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#import <CoreGraphics/CoreGraphics.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
typedef void(^ASImageCacherCompletion)(UIImage * _Nullable imageFromCache);
|
||||||
|
|
||||||
@protocol ASImageCacheProtocol <NSObject>
|
@protocol ASImageCacheProtocol <NSObject>
|
||||||
|
|
||||||
@required
|
@required
|
||||||
/**
|
/**
|
||||||
@abstract Attempts to fetch an image with the given URL from the cache.
|
@deprecated This method is deprecated @see cachedImageWithURL:callbackQueue:completion: instead
|
||||||
@param URL The URL of the image to retrieve from the cache.
|
|
||||||
@param callbackQueue The queue to call `completion` on. If this value is nil, @{ref completion} will be invoked on the
|
|
||||||
main-queue.
|
|
||||||
@param completion The block to be called when the cache has either hit or missed.
|
|
||||||
@param imageFromCache The image that was retrieved from the cache, if the image could be retrieved; nil otherwise.
|
|
||||||
@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)fetchCachedImageWithURL:(nullable NSURL *)URL
|
- (void)fetchCachedImageWithURL:(nullable NSURL *)URL
|
||||||
callbackQueue:(nullable dispatch_queue_t)callbackQueue
|
callbackQueue:(nullable dispatch_queue_t)callbackQueue
|
||||||
completion:(void (^)(CGImageRef _Nullable imageFromCache))completion;
|
completion:(void (^)(CGImageRef _Nullable imageFromCache))completion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@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.
|
||||||
|
@param callbackQueue The queue to call `completion` on. If this value is nil, @{ref completion} will be invoked on the
|
||||||
|
main-queue.
|
||||||
|
@param completion The block to be called when the cache has either hit or missed.
|
||||||
|
@param imageFromCache The image that was retrieved from the cache, if the image could be retrieved; nil otherwise.
|
||||||
|
@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
|
||||||
|
completion:(ASImageCacherCompletion)completion;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
typedef void(^ASImageDownloaderCompletion)(UIImage * _Nullable image, NSError * _Nullable error, id _Nullable downloadIdentifier);
|
||||||
|
typedef void(^ASImageDownloaderProgress)(CGFloat progress);
|
||||||
|
typedef void(^ASImageDownloaderProgressImage)(UIImage *progressImage, id _Nullable downloadIdentifier);
|
||||||
|
|
||||||
|
typedef NS_ENUM(NSUInteger, ASImageDownloaderPriority) {
|
||||||
|
ASImageDownloaderPriorityNormal = 0,
|
||||||
|
ASImageDownloaderPriorityDisplay,
|
||||||
|
};
|
||||||
|
|
||||||
@protocol ASImageDownloaderProtocol <NSObject>
|
@protocol ASImageDownloaderProtocol <NSObject>
|
||||||
|
|
||||||
@required
|
@required
|
||||||
/**
|
|
||||||
@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.
|
|
||||||
*/
|
|
||||||
- (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 Cancels an image download.
|
@abstract Cancels an image download.
|
||||||
@@ -58,7 +58,58 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
`downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:`.
|
`downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:`.
|
||||||
@discussion This method has no effect if `downloadIdentifier` is nil.
|
@discussion This method has no effect if `downloadIdentifier` is nil.
|
||||||
*/
|
*/
|
||||||
- (void)cancelImageDownloadForIdentifier:(nullable id)downloadIdentifier;
|
- (void)cancelImageDownloadForIdentifier:(id)downloadIdentifier;
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@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.
|
||||||
|
@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.
|
||||||
|
*/
|
||||||
|
- (nullable id)downloadImageWithURL:(NSURL *)URL
|
||||||
|
callbackQueue:(dispatch_queue_t)callbackQueue
|
||||||
|
downloadProgress:(nullable ASImageDownloaderProgress)downloadProgress
|
||||||
|
completion:(nullable ASImageDownloaderCompletion)completion;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@abstract Sets block to be called when a progress image is available.
|
||||||
|
@param progressBlock The block to be invoked when the download has a progressive render of an image available.
|
||||||
|
@param callbackQueue The queue to call `progressBlock` on.
|
||||||
|
@param downloadIdentifier The opaque download identifier object returned from
|
||||||
|
`downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:`.
|
||||||
|
*/
|
||||||
|
- (void)setProgressImageBlock:(nullable ASImageDownloaderProgressImage)progressBlock
|
||||||
|
callbackQueue:(dispatch_queue_t)callbackQueue
|
||||||
|
withDownloadIdentifier:(id)downloadIdentifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@abstract Called to indicate what priority an image should be downloaded at.
|
||||||
|
@param priority The priority at which the image should be downloaded.
|
||||||
|
@param downloadIdentifier The opaque download identifier object returned from
|
||||||
|
`downloadImageWithURL:callbackQueue:downloadProgressBlock:completion:`.
|
||||||
|
*/
|
||||||
|
- (void)setPriority:(ASImageDownloaderPriority)priority
|
||||||
|
withDownloadIdentifier:(id)downloadIdentifier;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
16
AsyncDisplayKit/Details/ASPINRemoteImageDownloader.h
Normal file
16
AsyncDisplayKit/Details/ASPINRemoteImageDownloader.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// ASPINRemoteImageDownloader.h
|
||||||
|
// Pods
|
||||||
|
//
|
||||||
|
// Created by Garrett Moon on 2/5/16.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import "ASImageProtocols.h"
|
||||||
|
|
||||||
|
@interface ASPINRemoteImageDownloader : NSObject <ASImageCacheProtocol, ASImageDownloaderProtocol>
|
||||||
|
|
||||||
|
+ (instancetype)sharedDownloader;
|
||||||
|
|
||||||
|
@end
|
||||||
97
AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m
Normal file
97
AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// ASPINRemoteImageDownloader.m
|
||||||
|
// Pods
|
||||||
|
//
|
||||||
|
// Created by Garrett Moon on 2/5/16.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifdef PIN_REMOTE_IMAGE
|
||||||
|
#import "ASPINRemoteImageDownloader.h"
|
||||||
|
#import <PINRemoteImage/PINRemoteImageManager.h>
|
||||||
|
#import <PINCache/PINCache.h>
|
||||||
|
|
||||||
|
@implementation ASPINRemoteImageDownloader
|
||||||
|
|
||||||
|
+ (instancetype)sharedDownloader
|
||||||
|
{
|
||||||
|
static ASPINRemoteImageDownloader *sharedDownloader = nil;
|
||||||
|
static dispatch_once_t once = 0;
|
||||||
|
dispatch_once(&once, ^{
|
||||||
|
sharedDownloader = [[ASPINRemoteImageDownloader alloc] init];
|
||||||
|
});
|
||||||
|
return sharedDownloader;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark ASImageProtocols
|
||||||
|
|
||||||
|
- (void)fetchCachedImageWithURL:(NSURL *)URL
|
||||||
|
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];
|
||||||
|
|
||||||
|
dispatch_async(callbackQueue, ^{
|
||||||
|
completion([image CGImage]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@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.
|
||||||
|
*/
|
||||||
|
- (nullable id)downloadImageWithURL:(NSURL *)URL
|
||||||
|
callbackQueue:(dispatch_queue_t)callbackQueue
|
||||||
|
downloadProgressBlock:(void (^)(CGFloat progress))downloadProgressBlock
|
||||||
|
completion:(void (^)(CGImageRef image, NSError * error, id downloadIdentifier))completion
|
||||||
|
{
|
||||||
|
return [[PINRemoteImageManager sharedImageManager] downloadImageWithURL:URL completion:^(PINRemoteImageManagerResult *result) {
|
||||||
|
dispatch_async(callbackQueue, ^{
|
||||||
|
completion([result.image CGImage], result.error, result.UUID);
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@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");
|
||||||
|
[[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");
|
||||||
|
|
||||||
|
[[PINRemoteImageManager sharedImageManager] setProgressCallback:^(PINRemoteImageManagerResult * _Nonnull result) {
|
||||||
|
dispatch_async(callbackQueue, ^{
|
||||||
|
progressBlock(result.image, result.UUID);
|
||||||
|
});
|
||||||
|
} ofTaskWithUUID:downloadIdentifier];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setPriority:(ASImageDownloaderPriority)priority withDownloadIdentifier:(id)downloadIdentifier
|
||||||
|
{
|
||||||
|
NSAssert([downloadIdentifier isKindOfClass:[NSUUID class]], @"downloadIdentifier must be NSUUID");
|
||||||
|
|
||||||
|
[[PINRemoteImageManager sharedImageManager] setPriority:PINRemoteImageManagerPriorityHigh ofTaskWithUUID:downloadIdentifier];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
#endif
|
||||||
@@ -145,14 +145,14 @@ static BOOL ASRunRunLoopUntilBlockIsTrue(BOOL (^block)())
|
|||||||
NSArray *URL;
|
NSArray *URL;
|
||||||
[inv getArgument:&URL atIndex:2];
|
[inv getArgument:&URL atIndex:2];
|
||||||
|
|
||||||
void (^completionBlock)(CGImageRef);
|
ASImageCacherCompletion completionBlock;
|
||||||
[inv getArgument:&completionBlock atIndex:4];
|
[inv getArgument:&completionBlock atIndex:4];
|
||||||
|
|
||||||
// Call the completion block with our test image and URL.
|
// Call the completion block with our test image and URL.
|
||||||
NSURL *testImageURL = [self _testImageURL];
|
NSURL *testImageURL = [self _testImageURL];
|
||||||
XCTAssertEqualObjects(URL, testImageURL, @"Fetching URL other than test image");
|
XCTAssertEqualObjects(URL, testImageURL, @"Fetching URL other than test image");
|
||||||
completionBlock([self _testImage].CGImage);
|
completionBlock([self _testImage]);
|
||||||
}] fetchCachedImageWithURL:[OCMArg any] callbackQueue:[OCMArg any] completion:[OCMArg any]];
|
}] cachedImageWithURL:[OCMArg any] callbackQueue:[OCMArg any] completion:[OCMArg any]];
|
||||||
|
|
||||||
imageNode.imageIdentifiers = @[imageIdentifier];
|
imageNode.imageIdentifiers = @[imageIdentifier];
|
||||||
// Kick off loading.
|
// Kick off loading.
|
||||||
@@ -302,25 +302,25 @@ static BOOL ASRunRunLoopUntilBlockIsTrue(BOOL (^block)())
|
|||||||
// Mock a cache miss.
|
// Mock a cache miss.
|
||||||
id mockCache = [OCMockObject mockForProtocol:@protocol(ASImageCacheProtocol)];
|
id mockCache = [OCMockObject mockForProtocol:@protocol(ASImageCacheProtocol)];
|
||||||
[[[mockCache stub] andDo:^(NSInvocation *inv) {
|
[[[mockCache stub] andDo:^(NSInvocation *inv) {
|
||||||
void (^completion)(CGImageRef imageFromCache);
|
ASImageCacherCompletion completion;
|
||||||
[inv getArgument:&completion atIndex:4];
|
[inv getArgument:&completion atIndex:4];
|
||||||
completion(nil);
|
completion(nil);
|
||||||
}] fetchCachedImageWithURL:[OCMArg any] callbackQueue:[OCMArg any] completion:[OCMArg any]];
|
}] cachedImageWithURL:[OCMArg any] callbackQueue:[OCMArg any] completion:[OCMArg any]];
|
||||||
|
|
||||||
// Mock a 50%-progress URL download.
|
// Mock a 50%-progress URL download.
|
||||||
id mockDownloader = [OCMockObject mockForProtocol:@protocol(ASImageDownloaderProtocol)];
|
id mockDownloader = [OCMockObject mockForProtocol:@protocol(ASImageDownloaderProtocol)];
|
||||||
const CGFloat mockedProgress = 0.5;
|
const CGFloat mockedProgress = 0.5;
|
||||||
[[[mockDownloader stub] andDo:^(NSInvocation *inv) {
|
[[[mockDownloader stub] andDo:^(NSInvocation *inv) {
|
||||||
// Simulate progress.
|
// Simulate progress.
|
||||||
void (^progressBlock)(CGFloat progress);
|
ASImageDownloaderProgress progressBlock;
|
||||||
[inv getArgument:&progressBlock atIndex:4];
|
[inv getArgument:&progressBlock atIndex:4];
|
||||||
progressBlock(mockedProgress);
|
progressBlock(mockedProgress);
|
||||||
|
|
||||||
// Simulate completion.
|
// Simulate completion.
|
||||||
void (^completionBlock)(CGImageRef image, NSError *error);
|
ASImageDownloaderCompletion completionBlock;
|
||||||
[inv getArgument:&completionBlock atIndex:5];
|
[inv getArgument:&completionBlock atIndex:5];
|
||||||
completionBlock([self _testImage].CGImage, nil);
|
completionBlock([self _testImage], nil, nil);
|
||||||
}] downloadImageWithURL:[OCMArg any] callbackQueue:[OCMArg any] downloadProgressBlock:[OCMArg any] completion:[OCMArg any]];
|
}] downloadImageWithURL:[OCMArg any] callbackQueue:[OCMArg any] downloadProgress:[OCMArg any] completion:[OCMArg any]];
|
||||||
|
|
||||||
ASMultiplexImageNode *imageNode = [[ASMultiplexImageNode alloc] initWithCache:mockCache downloader:mockDownloader];
|
ASMultiplexImageNode *imageNode = [[ASMultiplexImageNode alloc] initWithCache:mockCache downloader:mockDownloader];
|
||||||
NSNumber *imageIdentifier = @1;
|
NSNumber *imageIdentifier = @1;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// multiplex image node!
|
// multiplex image node!
|
||||||
// NB: we're using a custom downloader with an artificial delay for this demo, but ASBasicImageDownloader works too!
|
// NB: we're using a custom downloader with an artificial delay for this demo, but ASPINRemoteImageDownloader works too!
|
||||||
_imageNode = [[ASMultiplexImageNode alloc] initWithCache:nil downloader:self];
|
_imageNode = [[ASMultiplexImageNode alloc] initWithCache:nil downloader:self];
|
||||||
_imageNode.dataSource = self;
|
_imageNode.dataSource = self;
|
||||||
_imageNode.delegate = self;
|
_imageNode.delegate = self;
|
||||||
|
|||||||
Reference in New Issue
Block a user