diff --git a/AsyncDisplayKit/ASMultiplexImageNode.h b/AsyncDisplayKit/ASMultiplexImageNode.h index 308eedd144..eb49c48a64 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.h +++ b/AsyncDisplayKit/ASMultiplexImageNode.h @@ -68,6 +68,11 @@ typedef NS_ENUM(NSUInteger, ASMultiplexImageNodeErrorCode) { */ @property (nonatomic, readwrite, assign) BOOL downloadsIntermediateImages; +/** + * @abstract Indicates that the receiver should stop loading if it encounters an error while loading an intermediate image identifier. Defaults to NO. + */ +@property (nonatomic, readwrite, assign) BOOL haltsLoadingOnError; + /** * @abstract An array of identifiers representing various versions of an image for ASMultiplexImageNode to display. * diff --git a/AsyncDisplayKit/ASMultiplexImageNode.mm b/AsyncDisplayKit/ASMultiplexImageNode.mm index 9abf6b8b2f..5beac2323f 100644 --- a/AsyncDisplayKit/ASMultiplexImageNode.mm +++ b/AsyncDisplayKit/ASMultiplexImageNode.mm @@ -62,11 +62,13 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent // Image flags. BOOL _downloadsIntermediateImages; // Defaults to NO. + BOOL _haltsLoadingOnError; // Defaults to NO. OSSpinLock _imageIdentifiersLock; NSArray *_imageIdentifiers; id _loadedImageIdentifier; id _loadingImageIdentifier; id _displayedImageIdentifier; + id _failedImageIdentifier; // Reset to nil whenever an image is successfully loaded // Networking. id _downloadIdentifier; @@ -353,9 +355,11 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent { OSSpinLockLock(&_imageIdentifiersLock); + id currentImageIdentifier = _failedImageIdentifier != nil ? _failedImageIdentifier : _loadedImageIdentifier; + // If we've already loaded the best identifier, we've got nothing else to do. id bestImageIdentifier = ([_imageIdentifiers count] > 0) ? _imageIdentifiers[0] : nil; - if (!bestImageIdentifier || [_loadedImageIdentifier isEqual:bestImageIdentifier]) { + if (!bestImageIdentifier || [currentImageIdentifier isEqual:bestImageIdentifier]) { OSSpinLockUnlock(&_imageIdentifiersLock); return nil; } @@ -368,15 +372,15 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent } // Otherwise, load progressively. else { - NSUInteger loadedIndex = [_imageIdentifiers indexOfObject:_loadedImageIdentifier]; + NSUInteger currentIndex = [_imageIdentifiers indexOfObject:currentImageIdentifier]; // If nothing has loaded yet, load the worst identifier. - if (loadedIndex == NSNotFound) { + if (currentIndex == NSNotFound) { nextImageIdentifierToDownload = [_imageIdentifiers lastObject]; } // Otherwise, load the next best identifier (if there is one) - else if (loadedIndex > 0) { - nextImageIdentifierToDownload = _imageIdentifiers[loadedIndex - 1]; + else if (currentIndex > 0) { + nextImageIdentifierToDownload = _imageIdentifiers[currentIndex - 1]; } } @@ -588,10 +592,16 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent #pragma mark - - (void)_finishedLoadingImage:(UIImage *)image forIdentifier:(id)imageIdentifier error:(NSError *)error { - // If we failed to load, we stop the loading process. + // If we failed to load and _haltsLoadingOnError is YES, we stop the loading process. // Note that if we bailed before we began downloading because the best identifier changed, we don't bail, but rather just begin loading the best image identifier. - if (error && error.code != ASMultiplexImageNodeErrorCodeBestImageIdentifierChanged) - return; + if (error && error.code != ASMultiplexImageNodeErrorCodeBestImageIdentifierChanged) { + if (_haltsLoadingOnError) { + return; + } + _failedImageIdentifier = imageIdentifier; + } else { + _failedImageIdentifier = nil; + } OSSpinLockLock(&_imageIdentifiersLock); NSUInteger imageIdentifierCount = [_imageIdentifiers count];