Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit f212545

Browse files
authored
[Layout] Add extensibility support to ASLayoutElementStyle (#2975)
* Add extensibility support to ASLayoutElementStyle * Fix some typo
1 parent d2da941 commit f212545

3 files changed

Lines changed: 194 additions & 1 deletion

File tree

AsyncDisplayKit.xcodeproj/project.pbxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,7 @@
588588
698C8B601CAB49FC0052DC3F /* ASLayoutElementExtensibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutElementExtensibility.h; path = AsyncDisplayKit/Layout/ASLayoutElementExtensibility.h; sourceTree = "<group>"; };
589589
698DFF431E36B6C9002891F1 /* ASStackLayoutSpecUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASStackLayoutSpecUtilities.h; sourceTree = "<group>"; };
590590
698DFF461E36B7E9002891F1 /* ASLayoutSpecUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutSpecUtilities.h; sourceTree = "<group>"; };
591+
699B83501E3C1BA500433FA4 /* ASLayoutSpecTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayoutSpecTests.m; sourceTree = "<group>"; };
591592
69B225661D72535E00B25B22 /* ASDisplayNodeLayoutTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeLayoutTests.mm; sourceTree = "<group>"; };
592593
69B225681D7265DA00B25B22 /* ASXCTExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASXCTExtensions.h; sourceTree = "<group>"; };
593594
69CB62A91CB8165900024920 /* _ASDisplayViewAccessiblity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _ASDisplayViewAccessiblity.h; sourceTree = "<group>"; };
@@ -1020,6 +1021,7 @@
10201021
2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */,
10211022
69FEE53C1D95A9AF0086F066 /* ASLayoutElementStyleTests.m */,
10221023
695BE2541DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm */,
1024+
699B83501E3C1BA500433FA4 /* ASLayoutSpecTests.m */,
10231025
);
10241026
name = Tests;
10251027
path = AsyncDisplayKitTests;
@@ -1763,6 +1765,7 @@
17631765
CCB2F34D1D63CCC6004E6DE9 /* ASDisplayNodeSnapshotTests.m in Sources */,
17641766
AE6987C11DD04E1000B9E458 /* ASPagerNodeTests.m in Sources */,
17651767
058D0A3A195D057000B7D73C /* ASDisplayNodeTests.m in Sources */,
1768+
699B83511E3C1BA500433FA4 /* ASLayoutSpecTests.m in Sources */,
17661769
696FCB311D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm in Sources */,
17671770
69FEE53D1D95A9AF0086F066 /* ASLayoutElementStyleTests.m in Sources */,
17681771
CC4981B31D1A02BE004E13CC /* ASTableViewThrashTests.m in Sources */,

AsyncDisplayKit/Layout/ASLayoutElementExtensibility.h

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
#import <Foundation/NSGeometry.h>
1717
#endif
1818

19+
#import <objc/runtime.h>
20+
21+
#pragma mark - ASLayoutElementExtensibility
22+
1923
@protocol ASLayoutElementExtensibility <NSObject>
2024

2125
// The maximum number of extended values per type are defined in ASEnvironment.h above the ASEnvironmentStateExtensions
@@ -30,5 +34,80 @@
3034
- (void)setLayoutOptionExtensionEdgeInsets:(UIEdgeInsets)value atIndex:(int)idx;
3135
- (UIEdgeInsets)layoutOptionExtensionEdgeInsetsAtIndex:(int)idx;
3236

33-
3437
@end
38+
39+
#pragma mark - Dynamic Properties
40+
41+
/**
42+
* Unbox NSNumber based on the type
43+
*/
44+
#define ASDK_UNBOX_NUMBER(NUMBER, PROPERTY_TYPE) \
45+
const char *objCType = [NUMBER objCType]; \
46+
if (strcmp(objCType, @encode(BOOL)) == 0) { \
47+
return (PROPERTY_TYPE)[obj boolValue]; \
48+
} else if (strcmp(objCType, @encode(int)) == 0) { \
49+
return (PROPERTY_TYPE)[obj intValue]; \
50+
} else if (strcmp(objCType, @encode(NSInteger)) == 0) { \
51+
return (PROPERTY_TYPE)[obj integerValue]; \
52+
} else if (strcmp(objCType, @encode(NSUInteger)) == 0) { \
53+
return (PROPERTY_TYPE)[obj unsignedIntegerValue]; \
54+
} else if (strcmp(objCType, @encode(CGFloat)) == 0) { \
55+
return (PROPERTY_TYPE)[obj floatValue]; \
56+
} else { \
57+
NSAssert(NO, @"Data type not supported"); \
58+
} \
59+
60+
/**
61+
* Define a NSObject property
62+
*/
63+
#define ASDK_STYLE_PROP_OBJ(PROPERTY_TYPE, PROPERTY_NAME, SETTER_NAME) \
64+
@dynamic PROPERTY_NAME; \
65+
- (PROPERTY_TYPE)PROPERTY_NAME \
66+
{ \
67+
return (PROPERTY_TYPE)objc_getAssociatedObject(self, @selector(PROPERTY_NAME)); \
68+
} \
69+
\
70+
- (void)SETTER_NAME:(PROPERTY_TYPE)PROPERTY_NAME \
71+
{ \
72+
objc_setAssociatedObject(self, @selector(PROPERTY_NAME), PROPERTY_NAME, OBJC_ASSOCIATION_RETAIN); \
73+
} \
74+
75+
/**
76+
* Define an primitive property
77+
*/
78+
#define ASDK_STYLE_PROP_PRIM(PROPERTY_TYPE, PROPERTY_NAME, SETTER_NAME, DEFAULT_VALUE) \
79+
@dynamic PROPERTY_NAME; \
80+
- (PROPERTY_TYPE)PROPERTY_NAME \
81+
{ \
82+
id obj = objc_getAssociatedObject(self, @selector(PROPERTY_NAME)); \
83+
\
84+
if (obj != nil) { \
85+
ASDK_UNBOX_NUMBER(obj, PROPERTY_TYPE); \
86+
} \
87+
\
88+
return DEFAULT_VALUE;\
89+
} \
90+
\
91+
- (void)SETTER_NAME:(PROPERTY_TYPE)PROPERTY_NAME \
92+
{ \
93+
objc_setAssociatedObject(self, @selector(PROPERTY_NAME), @(PROPERTY_NAME), OBJC_ASSOCIATION_RETAIN); \
94+
} \
95+
96+
/**
97+
* Define an structure property
98+
*/
99+
#define ASDK_STYLE_PROP_STR(PROPERTY_TYPE, PROPERTY_NAME, SETTER_NAME, DEFAULT_STRUCT) \
100+
@dynamic PROPERTY_NAME; \
101+
- (PROPERTY_TYPE)PROPERTY_NAME \
102+
{ \
103+
id obj = objc_getAssociatedObject(self, @selector(PROPERTY_NAME)); \
104+
if (obj == nil) { \
105+
return DEFAULT_STRUCT; \
106+
} \
107+
PROPERTY_TYPE PROPERTY_NAME; [obj getValue:&PROPERTY_NAME]; return PROPERTY_NAME; \
108+
} \
109+
\
110+
- (void)SETTER_NAME:(PROPERTY_TYPE)PROPERTY_NAME \
111+
{ \
112+
objc_setAssociatedObject(self, @selector(PROPERTY_NAME), [NSValue value:&PROPERTY_NAME withObjCType:@encode(PROPERTY_TYPE)], OBJC_ASSOCIATION_RETAIN_NONATOMIC);\
113+
} \
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
//
2+
// ASLayoutSpecTests.m
3+
// AsyncDisplayKit
4+
//
5+
// Created by Michael Schneider on 1/27/17.
6+
// Copyright © 2017 Facebook. All rights reserved.
7+
//
8+
9+
#import <XCTest/XCTest.h>
10+
11+
#import <AsyncDisplayKit/AsyncDisplayKit.h>
12+
#import <AsyncDisplayKit/ASLayoutElementExtensibility.h>
13+
14+
#pragma mark - ASDKExtendedLayoutSpec
15+
16+
/*
17+
* Extend the ASDKExtendedLayoutElement
18+
* It adds a
19+
* - primitive / CGFloat (extendedWidth)
20+
* - struct / ASDimension (extendedDimension)
21+
* - primitive / ASStackLayoutDirection (extendedDirection)
22+
*/
23+
@protocol ASDKExtendedLayoutElement <NSObject>
24+
@property (assign, nonatomic) CGFloat extendedWidth;
25+
@property (assign, nonatomic) ASDimension extendedDimension;
26+
@property (copy, nonatomic) NSString *extendedName;
27+
@end
28+
29+
/*
30+
* Let the ASLayoutElementStyle conform to the ASDKExtendedLayoutElement protocol and add properties implementation
31+
*/
32+
@interface ASLayoutElementStyle (ASDKExtendedLayoutElement) <ASDKExtendedLayoutElement>
33+
@end
34+
35+
@implementation ASLayoutElementStyle (ASDKExtendedLayoutElement)
36+
ASDK_STYLE_PROP_PRIM(CGFloat, extendedWidth, setExtendedWidth, 0);
37+
ASDK_STYLE_PROP_STR(ASDimension, extendedDimension, setExtendedDimension, ASDimensionMake(ASDimensionUnitAuto, 0));
38+
ASDK_STYLE_PROP_OBJ(NSString *, extendedName, setExtendedName);
39+
@end
40+
41+
/*
42+
* As the ASLayoutableStyle conforms to the ASDKExtendedLayoutable protocol now, ASDKExtendedLayoutable properties
43+
* can be accessed in ASDKExtendedLayoutSpec
44+
*/
45+
@interface ASDKExtendedLayoutSpec : ASLayoutSpec
46+
@end
47+
48+
@implementation ASDKExtendedLayoutSpec
49+
50+
- (void)doSetSomeStyleValuesToChildren
51+
{
52+
for (id<ASLayoutElement> child in self.children) {
53+
child.style.extendedWidth = 100;
54+
child.style.extendedDimension = ASDimensionMake(100);
55+
child.style.extendedName = @"ASDK";
56+
}
57+
}
58+
59+
- (void)doUseSomeStyleValuesFromChildren
60+
{
61+
for (id<ASLayoutElement> child in self.children) {
62+
__unused CGFloat extendedWidth = child.style.extendedWidth;
63+
__unused ASDimension extendedDimension = child.style.extendedDimension;
64+
__unused NSString *extendedName = child.style.extendedName;
65+
}
66+
}
67+
68+
@end
69+
70+
71+
#pragma mark - ASLayoutSpecTests
72+
73+
@interface ASLayoutSpecTests : XCTestCase
74+
75+
@end
76+
77+
@implementation ASLayoutSpecTests
78+
79+
- (void)testSetPrimitiveToExtendedStyle
80+
{
81+
ASDisplayNode *node = [[ASDisplayNode alloc] init];
82+
node.style.extendedWidth = 100;
83+
XCTAssert(node.style.extendedWidth == 100, @"Primitive value should be set on extended style");
84+
}
85+
86+
- (void)testSetStructToExtendedStyle
87+
{
88+
ASDisplayNode *node = [[ASDisplayNode alloc] init];
89+
node.style.extendedDimension = ASDimensionMake(100);
90+
XCTAssertTrue(ASDimensionEqualToDimension(node.style.extendedDimension, ASDimensionMake(100)), @"Struct should be set on extended style");
91+
}
92+
93+
- (void)testSetObjectToExtendedStyle
94+
{
95+
NSString *extendedName = @"ASDK";
96+
97+
ASDisplayNode *node = [[ASDisplayNode alloc] init];
98+
node.style.extendedName = extendedName;
99+
XCTAssertEqualObjects(node.style.extendedName, extendedName, @"Object should be set on extended style");
100+
}
101+
102+
103+
- (void)testUseOfExtendedStyleProperties
104+
{
105+
ASDKExtendedLayoutSpec *extendedLayoutSpec = [ASDKExtendedLayoutSpec new];
106+
extendedLayoutSpec.children = @[[[ASDisplayNode alloc] init], [[ASDisplayNode alloc] init]];
107+
XCTAssertNoThrow([extendedLayoutSpec doSetSomeStyleValuesToChildren]);
108+
XCTAssertNoThrow([extendedLayoutSpec doUseSomeStyleValuesFromChildren]);
109+
}
110+
111+
@end

0 commit comments

Comments
 (0)