From 89d4193757d9e91956f69a6bce4068bc3dca310f Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Wed, 4 Jan 2017 18:57:23 +0000 Subject: [PATCH] Open source pi_imageNamed methods (#2859) --- AsyncDisplayKit/UIImage+ASConvenience.h | 21 ++++++++++++ AsyncDisplayKit/UIImage+ASConvenience.m | 43 +++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/AsyncDisplayKit/UIImage+ASConvenience.h b/AsyncDisplayKit/UIImage+ASConvenience.h index 0dc0668115..4edb6c726a 100644 --- a/AsyncDisplayKit/UIImage+ASConvenience.h +++ b/AsyncDisplayKit/UIImage+ASConvenience.h @@ -70,6 +70,27 @@ NS_ASSUME_NONNULL_BEGIN roundedCorners:(UIRectCorner)roundedCorners scale:(CGFloat)scale AS_WARN_UNUSED_RESULT; +/** + * A version of imageNamed that caches results because loading an image is expensive. + * Calling with the same name value will usually return the same object. A UIImage, + * after creation, is immutable and thread-safe so it's fine to share these objects across multiple threads. + * + * @param imageName The name of the image to load + * @return The loaded image or nil + */ ++ (UIImage *)as_imageNamed:(NSString *)imageName; + +/** + * A version of imageNamed that caches results because loading an image is expensive. + * Calling with the same name value will usually return the same object. A UIImage, + * after creation, is immutable and thread-safe so it's fine to share these objects across multiple threads. + * + * @param imageName The name of the image to load + * @param traitCollection The traits associated with the intended environment for the image. + * @return The loaded image or nil + */ ++ (UIImage *)as_imageNamed:(NSString *)imageName compatibleWithTraitCollection:(nullable UITraitCollection *)traitCollection; + @end NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/UIImage+ASConvenience.m b/AsyncDisplayKit/UIImage+ASConvenience.m index b6ae5adba1..3af1435acb 100644 --- a/AsyncDisplayKit/UIImage+ASConvenience.m +++ b/AsyncDisplayKit/UIImage+ASConvenience.m @@ -122,4 +122,47 @@ return result; } +#pragma mark - as_imageNamed + +UIImage *cachedImageNamed(NSString *imageName, UITraitCollection *traitCollection) +{ + static NSCache *imageCache = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + // Because NSCache responds to memory warnings, we do not need an explicit limit. + // all of these objects contain compressed image data and are relatively small + // compared to the backing stores of text and image views. + imageCache = [[NSCache alloc] init]; + }); + + UIImage *image = nil; + if ([imageName length] > 0) { + NSString *imageKey = imageName; + if (traitCollection) { + char imageKeyBuffer[256]; + snprintf(imageKeyBuffer, sizeof(imageKeyBuffer), "%s|%ld|%ld", imageName.UTF8String, (long)traitCollection.horizontalSizeClass, (long)traitCollection.verticalSizeClass); + imageKey = [NSString stringWithUTF8String:imageKeyBuffer]; + } + + image = [imageCache objectForKey:imageKey]; + if (!image) { + image = [UIImage imageNamed:imageName inBundle:nil compatibleWithTraitCollection:traitCollection]; + if (image) { + [imageCache setObject:image forKey:imageKey]; + } + } + } + return image; +} + ++ (UIImage *)as_imageNamed:(NSString *)imageName +{ + return cachedImageNamed(imageName, nil); +} + ++ (UIImage *)as_imageNamed:(NSString *)imageName compatibleWithTraitCollection:(UITraitCollection *)traitCollection +{ + return cachedImageNamed(imageName, traitCollection); +} + @end