Skip to content

Commit

Permalink
Add support for loading image variants through Asset catalogs (Textur…
Browse files Browse the repository at this point in the history
…eGroup#1630)

Currently ASImageNode would initially load the correct asset from the asset catalog but would not respond to changes in trait collections that would require loading a different asset from the asset catalog. This change allows use to use `-[UIImage imageAsset]` to reference the asset catalog entry for the current image and load the appropriate version based on the current trait collection
  • Loading branch information
vovasty authored and matthewd1234 committed Aug 25, 2019
1 parent b26e208 commit 21ad959
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 6 deletions.
8 changes: 6 additions & 2 deletions AsyncDisplayKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
044285101BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0442850C1BAA64EC00D16268 /* ASTwoDimensionalArrayUtils.mm */; };
052EE0661A159FEF002C6279 /* ASMultiplexImageNodeTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 052EE0651A159FEF002C6279 /* ASMultiplexImageNodeTests.mm */; };
052EE06B1A15A0D8002C6279 /* TestResources in Resources */ = {isa = PBXBuildFile; fileRef = 052EE06A1A15A0D8002C6279 /* TestResources */; };
056D21551ABCEF50001107EF /* ASImageNodeSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 056D21541ABCEF50001107EF /* ASImageNodeSnapshotTests.mm */; };
057D02C41AC0A66700C7AC3C /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 057D02C31AC0A66700C7AC3C /* main.mm */; };
057D02C71AC0A66700C7AC3C /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 057D02C61AC0A66700C7AC3C /* AppDelegate.mm */; };
058D09BE195D04C000B7D73C /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 058D09BD195D04C000B7D73C /* XCTest.framework */; };
Expand Down Expand Up @@ -323,6 +322,8 @@
C018DF21216BF26700181FDA /* ASAbstractLayoutController+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = C018DF20216BF26600181FDA /* ASAbstractLayoutController+FrameworkPrivate.h */; };
C057D9BD20B5453D00FC9112 /* ASTextNode2SnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = C057D9BC20B5453D00FC9112 /* ASTextNode2SnapshotTests.mm */; };
C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */ = {isa = PBXBuildFile; fileRef = B0F880581BEAEC7500D17647 /* ASTableNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
CC01EB6D23105C2000CDB61A /* TestAsset.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CC01EB6C23105C2000CDB61A /* TestAsset.xcassets */; };
CC01EB6F23105C7F00CDB61A /* ASImageNodeSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 056D21541ABCEF50001107EF /* ASImageNodeSnapshotTests.mm */; };
CC034A091E60BEB400626263 /* ASDisplayNode+Convenience.h in Headers */ = {isa = PBXBuildFile; fileRef = CC034A071E60BEB400626263 /* ASDisplayNode+Convenience.h */; settings = {ATTRIBUTES = (Public, ); }; };
CC034A0A1E60BEB400626263 /* ASDisplayNode+Convenience.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC034A081E60BEB400626263 /* ASDisplayNode+Convenience.mm */; };
CC034A131E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = CC034A111E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -852,6 +853,7 @@
BDC2D162BD55A807C1475DA5 /* Pods-AsyncDisplayKitTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AsyncDisplayKitTests.profile.xcconfig"; path = "Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests.profile.xcconfig"; sourceTree = "<group>"; };
C018DF20216BF26600181FDA /* ASAbstractLayoutController+FrameworkPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASAbstractLayoutController+FrameworkPrivate.h"; sourceTree = "<group>"; };
C057D9BC20B5453D00FC9112 /* ASTextNode2SnapshotTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ASTextNode2SnapshotTests.mm; sourceTree = "<group>"; };
CC01EB6C23105C2000CDB61A /* TestAsset.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = TestAsset.xcassets; sourceTree = "<group>"; };
CC034A071E60BEB400626263 /* ASDisplayNode+Convenience.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+Convenience.h"; sourceTree = "<group>"; };
CC034A081E60BEB400626263 /* ASDisplayNode+Convenience.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASDisplayNode+Convenience.mm"; sourceTree = "<group>"; };
CC034A111E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AsyncDisplayKit+IGListKitMethods.h"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1395,6 +1397,7 @@
058D09C6195D04C000B7D73C /* Supporting Files */ = {
isa = PBXGroup;
children = (
CC01EB6C23105C2000CDB61A /* TestAsset.xcassets */,
CC0F88691E4286FA00576FED /* ReferenceImages_64 */,
CC0F886A1E4286FA00576FED /* ReferenceImages_iOS_10 */,
058D09C7195D04C000B7D73C /* AsyncDisplayKitTests-Info.plist */,
Expand Down Expand Up @@ -2232,6 +2235,7 @@
CC0F886C1E4286FA00576FED /* ReferenceImages_64 in Resources */,
CC0F886D1E4286FA00576FED /* ReferenceImages_iOS_10 in Resources */,
052EE06B1A15A0D8002C6279 /* TestResources in Resources */,
CC01EB6D23105C2000CDB61A /* TestAsset.xcassets in Resources */,
058D09CA195D04C000B7D73C /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -2293,6 +2297,7 @@
ACF6ED5C1B178DC700DA7C62 /* ASCenterLayoutSpecSnapshotTests.mm in Sources */,
9F06E5CD1B4CAF4200F015D8 /* ASCollectionViewTests.mm in Sources */,
2911485C1A77147A005D0878 /* ASControlNodeTests.mm in Sources */,
CC01EB6F23105C7F00CDB61A /* ASImageNodeSnapshotTests.mm in Sources */,
CC3B208E1C3F7D0A00798563 /* ASWeakSetTests.mm in Sources */,
F711994E1D20C21100568860 /* ASDisplayNodeExtrasTests.mm in Sources */,
BB5FC3CE1F9BA689007F191E /* ASNavigationControllerTests.mm in Sources */,
Expand Down Expand Up @@ -2320,7 +2325,6 @@
CCE4F9B31F0D60AC00062E4E /* ASIntegerMapTests.mm in Sources */,
058D0A3B195D057000B7D73C /* ASDisplayNodeTestsHelper.mm in Sources */,
83A7D95E1D446A6E00BF333E /* ASWeakMapTests.mm in Sources */,
056D21551ABCEF50001107EF /* ASImageNodeSnapshotTests.mm in Sources */,
AC026B581BD3F61800BBC17E /* ASAbsoluteLayoutSpecSnapshotTests.mm in Sources */,
ACF6ED5E1B178DC700DA7C62 /* ASInsetLayoutSpecSnapshotTests.mm in Sources */,
ACF6ED601B178DC700DA7C62 /* ASLayoutSpecSnapshotTestsHelper.mm in Sources */,
Expand Down
44 changes: 41 additions & 3 deletions Source/ASImageNode.mm
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ @interface ASImageNodeDrawParameters : NSObject {
ASDisplayNodeContextModifier _willDisplayNodeContentWithRenderingContext;
ASDisplayNodeContextModifier _didDisplayNodeContentWithRenderingContext;
ASImageNodeDrawParametersBlock _didDrawBlock;
#if AS_BUILD_UIUSERINTERFACESTYLE
UIUserInterfaceStyle userInterfaceStyle;
#endif
}

@end
Expand All @@ -74,7 +77,9 @@ @interface ASImageNodeContentsKey : NSObject
@property (nonatomic) ASDisplayNodeContextModifier willDisplayNodeContentWithRenderingContext;
@property (nonatomic) ASDisplayNodeContextModifier didDisplayNodeContentWithRenderingContext;
@property (nonatomic) asimagenode_modification_block_t imageModificationBlock;

#if AS_BUILD_UIUSERINTERFACESTYLE
@property UIUserInterfaceStyle userInterfaceStyle API_AVAILABLE(tvos(10.0), ios(12.0));
#endif
@end

@implementation ASImageNodeContentsKey
Expand All @@ -99,6 +104,9 @@ - (BOOL)isEqual:(id)object
&& [_tintColor isEqual:other.tintColor]
&& _willDisplayNodeContentWithRenderingContext == other.willDisplayNodeContentWithRenderingContext
&& _didDisplayNodeContentWithRenderingContext == other.didDisplayNodeContentWithRenderingContext
#if AS_BUILD_UIUSERINTERFACESTYLE
&& _userInterfaceStyle == other.userInterfaceStyle
#endif
&& _imageModificationBlock == other.imageModificationBlock;
} else {
return NO;
Expand Down Expand Up @@ -136,7 +144,6 @@ - (NSUInteger)hash

@end


@implementation ASImageNode
{
@private
Expand Down Expand Up @@ -312,6 +319,10 @@ - (NSObject *)drawParametersForAsyncLayer:(_ASDisplayLayer *)layer
drawParameters->_imageModificationBlock = _imageModificationBlock;
drawParameters->_willDisplayNodeContentWithRenderingContext = _willDisplayNodeContentWithRenderingContext;
drawParameters->_didDisplayNodeContentWithRenderingContext = _didDisplayNodeContentWithRenderingContext;
#if AS_BUILD_UIUSERINTERFACESTYLE
drawParameters->userInterfaceStyle = self.primitiveTraitCollection.userInterfaceStyle;
#endif


// Hack for now to retain the weak entry that was created while this drawing happened
drawParameters->_didDrawBlock = ^(ASWeakMapEntry *entry){
Expand Down Expand Up @@ -403,6 +414,12 @@ + (UIImage *)displayWithParameters:(id<NSObject>)parameter isCancelled:(NS_NOESC
return nil;
}

#if AS_BUILD_UIUSERINTERFACESTYLE
UIUserInterfaceStyle userInterfaceStyle = drawParameter->userInterfaceStyle;
#endif



ASImageNodeContentsKey *contentsKey = [[ASImageNodeContentsKey alloc] init];
contentsKey.image = image;
contentsKey.backingSize = backingSize;
Expand All @@ -413,7 +430,9 @@ + (UIImage *)displayWithParameters:(id<NSObject>)parameter isCancelled:(NS_NOESC
contentsKey.willDisplayNodeContentWithRenderingContext = willDisplayNodeContentWithRenderingContext;
contentsKey.didDisplayNodeContentWithRenderingContext = didDisplayNodeContentWithRenderingContext;
contentsKey.imageModificationBlock = imageModificationBlock;

#if AS_BUILD_UIUSERINTERFACESTYLE
contentsKey.userInterfaceStyle = userInterfaceStyle;
#endif
if (isCancelled()) {
return nil;
}
Expand Down Expand Up @@ -739,6 +758,25 @@ - (NSDictionary *)debugLabelAttributes
};
}

#if AS_BUILD_UIUSERINTERFACESTYLE
- (void)asyncTraitCollectionDidChangeWithPreviousTraitCollection:(ASPrimitiveTraitCollection)previousTraitCollection {
[super asyncTraitCollectionDidChangeWithPreviousTraitCollection:previousTraitCollection];

if (AS_AVAILABLE_IOS_TVOS(12, 10)) {
// update image if userInterfaceStyle was changed (dark mode)
if (_image != nil && self.primitiveTraitCollection.userInterfaceStyle != previousTraitCollection.userInterfaceStyle) {
UITraitCollection *tc = [UITraitCollection traitCollectionWithUserInterfaceStyle:self.primitiveTraitCollection.userInterfaceStyle];
// get an updated image from asset catalog
UIImage *updatedImage = [self.image.imageAsset imageWithTraitCollection:tc];
if ( updatedImage != nil ) {
_image = updatedImage;
}
// trigger needs display anyway, cause image might be dynamic itself (e.g. dynamic tint color)
[self setNeedsDisplay];
}
}
}
#endif
@end

#pragma mark - Extras
Expand Down
2 changes: 1 addition & 1 deletion Source/UIImage+ASConvenience.mm
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ @implementation UIImage (ASDKFastImageNamed)
NSString *imageKey = imageName;
if (traitCollection) {
char imageKeyBuffer[256];
snprintf(imageKeyBuffer, sizeof(imageKeyBuffer), "%s|%ld|%ld", imageName.UTF8String, (long)traitCollection.horizontalSizeClass, (long)traitCollection.verticalSizeClass);
snprintf(imageKeyBuffer, sizeof(imageKeyBuffer), "%s|%ld|%ld|%ld", imageName.UTF8String, (long)traitCollection.horizontalSizeClass, (long)traitCollection.verticalSizeClass, (long)traitCollection.userInterfaceStyle);
imageKey = [NSString stringWithUTF8String:imageKeyBuffer];
}

Expand Down
25 changes: 25 additions & 0 deletions Tests/ASImageNodeSnapshotTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,29 @@ - (void)testRoundedCornerBlock
ASSnapshotVerifyNode(node, nil);
}

#if AS_AT_LEAST_IOS13
- (void)testDynamicAssetImage
{
if (@available(iOS 13.0, *)) {
ASConfiguration *config = [ASConfiguration new];
config.experimentalFeatures = ASExperimentalTraitCollectionDidChangeWithPreviousCollection;
[ASConfigurationManager test_resetWithConfiguration:config];

UIImage *image = [UIImage imageNamed:@"light-dark" inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];
ASImageNode *node = [[ASImageNode alloc] init];
node.image = image;
ASDisplayNodeSizeToFitSize(node, image.size);

[[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight] performAsCurrentTraitCollection:^{
ASSnapshotVerifyNode(node, @"user_interface_style_light");
}];

[[UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark] performAsCurrentTraitCollection:^{
ASSnapshotVerifyNode(node, @"user_interface_style_dark");
}];

NSLog(@"%@", image);
}
}
#endif // #if AS_AT_LEAST_IOS13
@end
Binary file added ...ASImageNodeSnapshotTests/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added ...SImageNodeSnapshotTests/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions Tests/TestAsset.xcassets/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
52 changes: 52 additions & 0 deletions Tests/TestAsset.xcassets/light-dark.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "light.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "dark.png",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "2x",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
]
},
{
"idiom" : "universal",
"scale" : "3x"
},
{
"idiom" : "universal",
"scale" : "3x",
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
]
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 21ad959

Please sign in to comment.