diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 0d0b362b85..ade7937883 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1702,10 +1702,6 @@ static NSInteger incrementIfFound(NSInteger i) { [self exitHierarchyState:stateToEnterOrExit]; } } - - if ([newSupernode supportsUpwardPropagation]) { - ASEnvironmentStatePropagateUp(newSupernode, _environmentState.layoutOptionsState); - } } // Track that a node will be displayed as part of the current node hierarchy. @@ -1860,7 +1856,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) ASDN::MutexLocker l(_propertyLock); if (_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits) { ASLayoutSpec *layoutSpec = [self layoutSpecThatFits:constrainedSize]; - layoutSpec.parent = self; + layoutSpec.parent = self; // This causes upward propogation of any non-default layoutable values. layoutSpec.isMutable = NO; ASLayout *layout = [layoutSpec measureWithSizeRange:constrainedSize]; // Make sure layoutableObject of the root layout is `self`, so that the flattened layout will be structurally correct. diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index c61e7a966f..a74dcd941d 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -81,8 +81,8 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey"; id finalLayoutable = [child finalLayoutable]; if (finalLayoutable != child) { - // Layout options state of child needs to be copied to final layoutable - finalLayoutable.environmentState.layoutOptionsState = child.environmentState.layoutOptionsState; + // Layout options state of child needs to be copied to final layoutable, but don't override customized values. + ASEnvironmentStatePropagateUp(finalLayoutable, child.environmentState.layoutOptionsState); return finalLayoutable; } } @@ -99,10 +99,11 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey"; - (void)setParent:(id)parent { + // FIXME: Locking should be evaluated here. _parent is not widely used yet, though. _parent = parent; if ([parent supportsUpwardPropagation]) { - ASEnvironmentStatePropagateUp(parent, _environmentState.layoutOptionsState); + ASEnvironmentStatePropagateUp(parent, self.environmentState.layoutOptionsState); } } @@ -115,12 +116,11 @@ static NSString * const kDefaultChildrenKey = @"kDefaultChildrenKey"; { ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); id finalLayoutable = [self layoutableToAddFromLayoutable:child]; - BOOL needsToPropagateLayoutOptionsState = (child != finalLayoutable); self.layoutChildren[identifier] = finalLayoutable; - if (needsToPropagateLayoutOptionsState) { - // We only need to propagate up layout options in setChild: as up propagation is currently only supported for - // layout specification has with one child - [self propagateUpLayoutOptionsState]; + if ([finalLayoutable isKindOfClass:[ASLayoutSpec class]]) { + [(ASLayoutSpec *)finalLayoutable setParent:self]; // This will trigger upward propogation if needed. + } else if ([self supportsUpwardPropagation]) { + ASEnvironmentStatePropagateUp(self, finalLayoutable.environmentState.layoutOptionsState); // Probably an ASDisplayNode } } diff --git a/AsyncDisplayKit/Private/ASEnvironmentInternal.mm b/AsyncDisplayKit/Private/ASEnvironmentInternal.mm index 4bec0df268..7685203ea2 100644 --- a/AsyncDisplayKit/Private/ASEnvironmentInternal.mm +++ b/AsyncDisplayKit/Private/ASEnvironmentInternal.mm @@ -115,33 +115,33 @@ ASEnvironmentState ASEnvironmentMergeObjectAndState(ASEnvironmentState environme // For every field check if the parent value is equal to the default than propegate up the child value to // the parent - if (parentState.spacingBefore != defaultState.spacingBefore) { + if (parentState.spacingBefore == defaultState.spacingBefore) { parentState.spacingBefore = state.spacingBefore; } - if (parentState.spacingAfter != defaultState.spacingAfter) { + if (parentState.spacingAfter == defaultState.spacingAfter) { parentState.spacingAfter = state.spacingAfter; } - if (parentState.alignSelf != defaultState.alignSelf) { - parentState.alignSelf = defaultState.alignSelf; + if (parentState.alignSelf == defaultState.alignSelf) { + parentState.alignSelf = state.alignSelf; } - if (parentState.flexGrow != defaultState.flexGrow) { - parentState.flexGrow = defaultState.flexGrow; + if (parentState.flexGrow == defaultState.flexGrow) { + parentState.flexGrow = state.flexGrow; } - if (!ASRelativeDimensionEqualToRelativeDimension(parentState.flexBasis, defaultState.flexBasis)) { - parentState.flexBasis = defaultState.flexBasis; + if (ASRelativeDimensionEqualToRelativeDimension(parentState.flexBasis, defaultState.flexBasis)) { + parentState.flexBasis = state.flexBasis; } - if (parentState.alignSelf != defaultState.alignSelf) { - parentState.alignSelf = defaultState.alignSelf; + if (parentState.alignSelf == defaultState.alignSelf) { + parentState.alignSelf = state.alignSelf; } - if (parentState.ascender != defaultState.ascender) { - parentState.ascender = defaultState.ascender; + if (parentState.ascender == defaultState.ascender) { + parentState.ascender = state.ascender; } - if (!ASRelativeSizeRangeEqualToRelativeSizeRange(parentState.sizeRange, defaultState.sizeRange)) { - parentState.sizeRange = defaultState.sizeRange; + if (ASRelativeSizeRangeEqualToRelativeSizeRange(parentState.sizeRange, defaultState.sizeRange)) { + parentState.sizeRange = state.sizeRange; } if (CGPointEqualToPoint(parentState.layoutPosition, defaultState.layoutPosition)) { - parentState.layoutPosition = defaultState.layoutPosition; + parentState.layoutPosition = state.layoutPosition; } environmentState.layoutOptionsState = parentState; diff --git a/examples/SocialAppLayout/Sample/AppDelegate.h b/examples/SocialAppLayout/Sample/AppDelegate.h index db4bc0a921..2aa29369b4 100644 --- a/examples/SocialAppLayout/Sample/AppDelegate.h +++ b/examples/SocialAppLayout/Sample/AppDelegate.h @@ -15,6 +15,4 @@ @property (strong, nonatomic) UIWindow *window; - @end - diff --git a/examples/SocialAppLayout/Sample/AppDelegate.m b/examples/SocialAppLayout/Sample/AppDelegate.m index 4b977d79e0..5bd8203ef3 100644 --- a/examples/SocialAppLayout/Sample/AppDelegate.m +++ b/examples/SocialAppLayout/Sample/AppDelegate.m @@ -10,23 +10,17 @@ */ #import "AppDelegate.h" - #import "ViewController.h" -@interface AppDelegate () - -@end - @implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]]; [self.window makeKeyAndVisible]; return YES; - } @end diff --git a/examples/SocialAppLayout/Sample/CommentsNode.m b/examples/SocialAppLayout/Sample/CommentsNode.m index c2f33d1219..1e8bc94028 100644 --- a/examples/SocialAppLayout/Sample/CommentsNode.m +++ b/examples/SocialAppLayout/Sample/CommentsNode.m @@ -20,8 +20,8 @@ @implementation CommentsNode -- (instancetype)initWithCommentsCount:(NSInteger)comentsCount { - +- (instancetype)initWithCommentsCount:(NSInteger)comentsCount +{ self = [super init]; if (self) { _commentsCount = comentsCount; @@ -44,8 +44,8 @@ } -- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { - +- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize +{ ASStackLayoutSpec *mainStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:6.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:@[self.iconNode, self.countNode]]; // set sizeRange to make width fixed to 60 @@ -55,5 +55,4 @@ return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[mainStack]]; } - @end diff --git a/examples/SocialAppLayout/Sample/LikesNode.m b/examples/SocialAppLayout/Sample/LikesNode.m index b650398338..0a6eb9bc6a 100644 --- a/examples/SocialAppLayout/Sample/LikesNode.m +++ b/examples/SocialAppLayout/Sample/LikesNode.m @@ -21,8 +21,8 @@ @implementation LikesNode -- (instancetype)initWithLikesCount:(NSInteger)likesCount { - +- (instancetype)initWithLikesCount:(NSInteger)likesCount +{ self = [super init]; if (self) { _likesCount = likesCount; @@ -49,7 +49,7 @@ } -+ (BOOL) getYesOrNo ++ (BOOL)getYesOrNo { int tmp = (arc4random() % 30)+1; if (tmp % 5 == 0) { @@ -58,8 +58,8 @@ return NO; } -- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { - +- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize +{ ASStackLayoutSpec *mainStack = [ASStackLayoutSpec stackLayoutSpecWithDirection:ASStackLayoutDirectionHorizontal spacing:6.0 justifyContent:ASStackLayoutJustifyContentStart alignItems:ASStackLayoutAlignItemsCenter children:@[_iconNode, _countNode]]; // set sizeRange to make width fixed to 60 @@ -67,7 +67,6 @@ ASRelativeSize max = ASRelativeSizeMake(ASRelativeDimensionMakeWithPoints(60.0), ASRelativeDimensionMakeWithPoints(40.0)); mainStack.sizeRange = ASRelativeSizeRangeMake(min, max); return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[mainStack]]; - } @end diff --git a/examples/SocialAppLayout/Sample/Post.m b/examples/SocialAppLayout/Sample/Post.m index 1e3b1fc183..7bedb4e25a 100644 --- a/examples/SocialAppLayout/Sample/Post.m +++ b/examples/SocialAppLayout/Sample/Post.m @@ -12,5 +12,4 @@ #import "Post.h" @implementation Post - @end diff --git a/examples/SocialAppLayout/Sample/PostNode.m b/examples/SocialAppLayout/Sample/PostNode.m index b35028d494..fd570dc481 100644 --- a/examples/SocialAppLayout/Sample/PostNode.m +++ b/examples/SocialAppLayout/Sample/PostNode.m @@ -34,8 +34,8 @@ @implementation PostNode -- (instancetype)initWithPost:(Post *)post { - +- (instancetype)initWithPost:(Post *)post +{ self = [super init]; if (self) { _post = post; @@ -181,14 +181,19 @@ [super didLoad]; } -- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize { - +- (ASLayoutSpec *)layoutSpecThatFits:(ASSizeRange)constrainedSize +{ // Flexible spacer between username and time ASLayoutSpec *spacer = [[ASLayoutSpec alloc] init]; spacer.flexGrow = YES; - + + // NOTE: This inset is not actually required by the layout, but is an example of the upward propogation of layoutable + // properties. Specifically, .flexGrow from the child is transferred to the inset spec so they can expand together. + // Without this capability, it would be required to set insetSpacer.flexGrow = YES; + ASInsetLayoutSpec *insetSpacer = [ASInsetLayoutSpec insetLayoutSpecWithInsets:UIEdgeInsetsMake(0, 0, 0, 0) child:spacer]; + // Horizontal stack for name, username, via icon and time - NSMutableArray *layoutSpecChildren = [@[_nameNode, _usernameNode, spacer] mutableCopy]; + NSMutableArray *layoutSpecChildren = [@[_nameNode, _usernameNode, insetSpacer] mutableCopy]; if (_post.via != 0) { [layoutSpecChildren addObject:_viaNode]; } diff --git a/examples/SocialAppLayout/Sample/TextStyles.m b/examples/SocialAppLayout/Sample/TextStyles.m index 153b12407e..cc2b6bdffb 100644 --- a/examples/SocialAppLayout/Sample/TextStyles.m +++ b/examples/SocialAppLayout/Sample/TextStyles.m @@ -54,16 +54,16 @@ }; } -+ (NSDictionary *)cellControlStyle { - ++ (NSDictionary *)cellControlStyle +{ return @{ NSFontAttributeName : [UIFont systemFontOfSize:13.0], NSForegroundColorAttributeName: [UIColor lightGrayColor] }; } -+ (NSDictionary *)cellControlColoredStyle { - ++ (NSDictionary *)cellControlColoredStyle +{ return @{ NSFontAttributeName : [UIFont systemFontOfSize:13.0], NSForegroundColorAttributeName: [UIColor colorWithRed:59.0/255.0 green:89.0/255.0 blue:152.0/255.0 alpha:1.0] diff --git a/examples/SocialAppLayout/Sample/ViewController.h b/examples/SocialAppLayout/Sample/ViewController.h index 7352ff1109..76b893d103 100644 --- a/examples/SocialAppLayout/Sample/ViewController.h +++ b/examples/SocialAppLayout/Sample/ViewController.h @@ -12,7 +12,4 @@ #import @interface ViewController : UIViewController - - @end - diff --git a/examples/SocialAppLayout/Sample/ViewController.m b/examples/SocialAppLayout/Sample/ViewController.m index cbda71e3ab..c9500b1778 100644 --- a/examples/SocialAppLayout/Sample/ViewController.m +++ b/examples/SocialAppLayout/Sample/ViewController.m @@ -45,8 +45,8 @@ _tableView.asyncDelegate = nil; } -- (void)viewDidLoad { - +- (void)viewDidLoad +{ [super viewDidLoad]; self.tableView = [[ASTableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain asyncDataFetching:YES]; @@ -57,8 +57,8 @@ [self.view addSubview:self.tableView]; } -- (void)createSocialAppDataSource { - +- (void)createSocialAppDataSource +{ _socialAppDataSource = [[NSMutableArray alloc] init]; Post *newPost = [[Post alloc] init];