From 7de82b0b5b170c7c6a986cfd01e587ae29c9e882 Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Wed, 8 Jun 2016 11:10:01 -0700 Subject: [PATCH 1/3] Support loading animated images from the local filesystem --- AsyncDisplayKit/ASNetworkImageNode.mm | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/AsyncDisplayKit/ASNetworkImageNode.mm b/AsyncDisplayKit/ASNetworkImageNode.mm index b9f6514fb7..e24e380868 100755 --- a/AsyncDisplayKit/ASNetworkImageNode.mm +++ b/AsyncDisplayKit/ASNetworkImageNode.mm @@ -457,15 +457,27 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0}; } else { // First try to load the path directly, for efficiency assuming a developer who // doesn't want caching is trying to be as minimal as possible. - self.image = [UIImage imageWithContentsOfFile:_URL.path]; - if (!self.image) { + NSData *data = [NSData dataWithContentsOfURL:_URL]; + if (data == nil) { // If we couldn't find it, execute an -imageNamed:-like search so we can find resources even if the // extension is not provided in the path. This allows the same path to work regardless of shouldCacheImage. NSString *filename = [[NSBundle mainBundle] pathForResource:_URL.path.lastPathComponent ofType:nil]; - if (filename) { - self.image = [UIImage imageWithContentsOfFile:filename]; + if (filename != nil) { + data = [NSData dataWithContentsOfFile:filename]; } } + + // If the file may be an animated gif and then created an animated image. + id animatedImage = nil; + if (_downloaderImplementsAnimatedImage && data != nil && [_URL.pathExtension isEqualToString:@"gif"]) { + animatedImage = [_downloader animatedImageWithData:data]; + } + + if (animatedImage != nil) { + self.animatedImage = animatedImage; + } else { + self.image = [UIImage imageWithData:data]; + } } _imageLoaded = YES; From 1fb3ffc6f84bb1a8b8bdc5071c9b1ff3918c5671 Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Thu, 9 Jun 2016 10:01:59 -0700 Subject: [PATCH 2/3] Replace usage of imageWithData: with imageWithContentsOfFile: --- AsyncDisplayKit/ASNetworkImageNode.mm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/AsyncDisplayKit/ASNetworkImageNode.mm b/AsyncDisplayKit/ASNetworkImageNode.mm index e24e380868..fc2774d861 100755 --- a/AsyncDisplayKit/ASNetworkImageNode.mm +++ b/AsyncDisplayKit/ASNetworkImageNode.mm @@ -457,26 +457,27 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0}; } else { // First try to load the path directly, for efficiency assuming a developer who // doesn't want caching is trying to be as minimal as possible. - NSData *data = [NSData dataWithContentsOfURL:_URL]; - if (data == nil) { + UIImage *nonAnimatedImage = [UIImage imageWithContentsOfFile:_URL.path]; + if (nonAnimatedImage == nil) { // If we couldn't find it, execute an -imageNamed:-like search so we can find resources even if the // extension is not provided in the path. This allows the same path to work regardless of shouldCacheImage. NSString *filename = [[NSBundle mainBundle] pathForResource:_URL.path.lastPathComponent ofType:nil]; if (filename != nil) { - data = [NSData dataWithContentsOfFile:filename]; + nonAnimatedImage = [UIImage imageWithContentsOfFile:filename]; } } // If the file may be an animated gif and then created an animated image. id animatedImage = nil; - if (_downloaderImplementsAnimatedImage && data != nil && [_URL.pathExtension isEqualToString:@"gif"]) { + if (_downloaderImplementsAnimatedImage && [_URL.pathExtension isEqualToString:@"gif"]) { + NSData *data = [NSData dataWithContentsOfURL:_URL]; animatedImage = [_downloader animatedImageWithData:data]; } if (animatedImage != nil) { self.animatedImage = animatedImage; } else { - self.image = [UIImage imageWithData:data]; + self.image = nonAnimatedImage; } } From 91e6df0af920331fc7ef3ab5787633662f5db654 Mon Sep 17 00:00:00 2001 From: Eric Jensen Date: Thu, 9 Jun 2016 10:36:18 -0700 Subject: [PATCH 3/3] Add a way to check if data is in a format supported by a class implementing ASAnimatedImageProtocol --- AsyncDisplayKit/ASNetworkImageNode.mm | 6 +++++- AsyncDisplayKit/Details/ASImageProtocols.h | 9 +++++++++ AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m | 5 +++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/AsyncDisplayKit/ASNetworkImageNode.mm b/AsyncDisplayKit/ASNetworkImageNode.mm index fc2774d861..eaf9882f5e 100755 --- a/AsyncDisplayKit/ASNetworkImageNode.mm +++ b/AsyncDisplayKit/ASNetworkImageNode.mm @@ -469,9 +469,13 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0}; // If the file may be an animated gif and then created an animated image. id animatedImage = nil; - if (_downloaderImplementsAnimatedImage && [_URL.pathExtension isEqualToString:@"gif"]) { + if (_downloaderImplementsAnimatedImage) { NSData *data = [NSData dataWithContentsOfURL:_URL]; animatedImage = [_downloader animatedImageWithData:data]; + + if ([animatedImage respondsToSelector:@selector(isDataSupported:)] && [animatedImage isDataSupported:data] == NO) { + animatedImage = nil; + } } if (animatedImage != nil) { diff --git a/AsyncDisplayKit/Details/ASImageProtocols.h b/AsyncDisplayKit/Details/ASImageProtocols.h index ff6803bd8d..f7f8337a6b 100644 --- a/AsyncDisplayKit/Details/ASImageProtocols.h +++ b/AsyncDisplayKit/Details/ASImageProtocols.h @@ -142,12 +142,21 @@ withDownloadIdentifier:(id)downloadIdentifier; @protocol ASAnimatedImageProtocol +@optional + /** @abstract Should be called when the objects cover image is ready. @param coverImageReadyCallback a block which receives the cover image. */ @property (nonatomic, strong, readwrite) void (^coverImageReadyCallback)(UIImage *coverImage); +/** + @abstract Returns whether the supplied data contains a supported animated image format. + @param data the data to check if contains a supported animated image. + */ +- (BOOL)isDataSupported:(NSData *)data; + + @required /** diff --git a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m index 4ace07c87b..6eea964b34 100644 --- a/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m +++ b/AsyncDisplayKit/Details/ASPINRemoteImageDownloader.m @@ -56,6 +56,11 @@ return self.fileReady; } +- (BOOL)isDataSupported:(NSData *)data +{ + return [data pin_isGIF]; +} + @end #endif