diff --git a/AsyncDisplayKit.xcodeproj/project.pbxproj b/AsyncDisplayKit.xcodeproj/project.pbxproj index b0fac5c217..e573a8c423 100644 --- a/AsyncDisplayKit.xcodeproj/project.pbxproj +++ b/AsyncDisplayKit.xcodeproj/project.pbxproj @@ -214,7 +214,6 @@ 69E1006F1CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */; }; 69E100701CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */; }; 69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 69F6058D1D3DA27E00C8CA38 /* ASLayoutSpec+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F6058C1D3DA27E00C8CA38 /* ASLayoutSpec+Private.h */; }; 7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */ = {isa = PBXBuildFile; fileRef = AEEC47DF1C20C2DD00EC1693 /* ASVideoNode.h */; settings = {ATTRIBUTES = (Public, ); }; }; 764D83D51C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h in Headers */ = {isa = PBXBuildFile; fileRef = 764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */; settings = {ATTRIBUTES = (Public, ); }; }; 764D83D61C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m in Sources */ = {isa = PBXBuildFile; fileRef = 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */; }; @@ -966,7 +965,6 @@ 69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEnvironmentInternal.h; sourceTree = ""; }; 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEnvironmentInternal.mm; sourceTree = ""; }; 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASRangeControllerUpdateRangeProtocol+Beta.h"; sourceTree = ""; }; - 69F6058C1D3DA27E00C8CA38 /* ASLayoutSpec+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASLayoutSpec+Private.h"; sourceTree = ""; }; 6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = ""; }; 764D83D21C8EA515009B4FB8 /* AsyncDisplayKit+Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AsyncDisplayKit+Debug.h"; sourceTree = ""; }; 764D83D31C8EA515009B4FB8 /* AsyncDisplayKit+Debug.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "AsyncDisplayKit+Debug.m"; sourceTree = ""; }; @@ -1472,8 +1470,6 @@ 044285051BAA63FE00D16268 /* ASBatchFetching.h */, 044285061BAA63FE00D16268 /* ASBatchFetching.m */, 251B8EF61BBB3D690087C538 /* ASDataController+Subclasses.h */, - 8B0768B11CE752EC002E1453 /* ASDefaultPlaybackButton.h */, - 8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.m */, AEB7B0181C5962EA00662EF4 /* ASDefaultPlayButton.h */, AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.m */, 058D0A08195D050800B7D73C /* ASDisplayNode+AsyncDisplay.mm */, @@ -1482,17 +1478,16 @@ DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */, 058D0A0B195D050800B7D73C /* ASDisplayNode+UIViewBridge.mm */, 058D0A0C195D050800B7D73C /* ASDisplayNodeInternal.h */, - 69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */, - 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */, - 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */, - 058D0A0D195D050800B7D73C /* ASImageNode+CGExtras.h */, - 058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.m */, - ACF6ED431B17847A00DA7C62 /* ASInternalHelpers.h */, - ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.m */, - 69F6058C1D3DA27E00C8CA38 /* ASLayoutSpec+Private.h */, - ACF6ED451B17847A00DA7C62 /* ASLayoutSpecUtilities.h */, E52405B41C8FEF16004DC8E7 /* ASLayoutTransition.h */, E52405B21C8FEF03004DC8E7 /* ASLayoutTransition.mm */, + 69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */, + 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */, + 058D0A0D195D050800B7D73C /* ASImageNode+CGExtras.h */, + 058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.m */, + 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */, + ACF6ED431B17847A00DA7C62 /* ASInternalHelpers.h */, + ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.m */, + ACF6ED451B17847A00DA7C62 /* ASLayoutSpecUtilities.h */, 0442850B1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.h */, 0442850C1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm */, CC3B20811C3F76D600798563 /* ASPendingStateController.h */, @@ -1510,6 +1505,8 @@ CC3B20881C3F7A5400798563 /* ASWeakSet.m */, DBC452D91C5BF64600B16017 /* NSArray+Diffing.h */, DBC452DA1C5BF64600B16017 /* NSArray+Diffing.m */, + 8B0768B11CE752EC002E1453 /* ASDefaultPlaybackButton.h */, + 8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.m */, ); path = Private; sourceTree = ""; @@ -1743,7 +1740,6 @@ B350625B1B010F070018CF92 /* ASEqualityHelpers.h in Headers */, 680346941CE4052A0009FEB4 /* ASNavigationController.h in Headers */, B350621B1B010EFD0018CF92 /* ASFlowLayoutController.h in Headers */, - 69F6058D1D3DA27E00C8CA38 /* ASLayoutSpec+Private.h in Headers */, B350621D1B010EFD0018CF92 /* ASHighlightOverlayLayer.h in Headers */, C78F7E2B1BF7809800CDEAFC /* ASTableNode.h in Headers */, AC7A2C181BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */, diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index d875aabb5f..0b56764e6e 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -2981,15 +2981,6 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority"; } } -#pragma mark - NSFastEnumeration - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state - objects:(id __unsafe_unretained [])stackbuf - count:(NSUInteger)stackbufLength -{ - return [self.children countByEnumeratingWithState:state objects:stackbuf count:stackbufLength]; -} - ASEnvironmentLayoutOptionsForwarding ASEnvironmentLayoutExtensibilityForwarding diff --git a/AsyncDisplayKit/ASViewController.mm b/AsyncDisplayKit/ASViewController.mm index 9b355dd8e5..e754633ca0 100644 --- a/AsyncDisplayKit/ASViewController.mm +++ b/AsyncDisplayKit/ASViewController.mm @@ -289,7 +289,8 @@ ASVisibilityDepthImplementation; self.node.environmentState = environmentState; [self.node setNeedsLayout]; - for (id child in self.node) { + NSArray> *children = [self.node children]; + for (id child in children) { ASEnvironmentStatePropagateDown(child, environmentState.environmentTraitCollection); } } diff --git a/AsyncDisplayKit/Details/ASEnvironment.h b/AsyncDisplayKit/Details/ASEnvironment.h index 3717ae5d0d..4dad9fde9f 100644 --- a/AsyncDisplayKit/Details/ASEnvironment.h +++ b/AsyncDisplayKit/Details/ASEnvironment.h @@ -99,7 +99,7 @@ ASDISPLAYNODE_EXTERN_C_END * defined in an ASEnvironmentState up and down the ASEnvironment tree. To be able to define how merges of * States should happen, specific merge functions can be provided */ -@protocol ASEnvironment +@protocol ASEnvironment /// The environment collection of an object which class conforms to the ASEnvironment protocol - (ASEnvironmentState)environmentState; @@ -126,7 +126,6 @@ ASDISPLAYNODE_EXTERN_C_END /// sets a trait collection on this environment state. - (void)setEnvironmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection; - @end // ASCollection/TableNodes don't actually have ASCellNodes as subnodes. Because of this we can't rely on display trait diff --git a/AsyncDisplayKit/Layout/ASLayoutSpec.mm b/AsyncDisplayKit/Layout/ASLayoutSpec.mm index 18686178ac..4c66b3c129 100644 --- a/AsyncDisplayKit/Layout/ASLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASLayoutSpec.mm @@ -8,7 +8,7 @@ // of patent rights can be found in the PATENTS file in the same directory. // -#import "ASLayoutSpec+Private.h" +#import "ASLayoutSpec.h" #import "ASAssert.h" #import "ASEnvironmentInternal.h" @@ -17,13 +17,16 @@ #import "ASThread.h" #import "ASTraitCollection.h" +#import +#import #import +typedef std::map, std::less> ASChildMap; + @interface ASLayoutSpec() { ASEnvironmentState _environmentState; ASDN::RecursiveMutex __instanceLock__; - ASChildrenMap _childrenMap; - unsigned long _mutations; + ASChildMap _children; } @end @@ -32,7 +35,6 @@ // these dynamic properties all defined in ASLayoutOptionsPrivate.m @dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis, alignSelf, ascender, descender, sizeRange, layoutPosition, layoutableType; -@synthesize parent = _parent; @synthesize isFinalLayoutable = _isFinalLayoutable; - (instancetype)init @@ -42,7 +44,6 @@ } _isMutable = YES; _environmentState = ASEnvironmentStateMakeDefault(); - _mutations = 0; return self; } @@ -104,8 +105,6 @@ return child; } -#pragma mark - Parent - - (void)setParent:(id)parent { // FIXME: Locking should be evaluated here. _parent is not widely used yet, though. @@ -116,16 +115,18 @@ } } -- (id)parent -{ - return _parent; -} - -#pragma mark - Children - - (void)setChild:(id)child { - [self setChild:child forIndex:0]; + ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); + if (child) { + id finalLayoutable = [self layoutableToAddFromLayoutable:child]; + if (finalLayoutable) { + _children[0] = finalLayoutable; + [self propagateUpLayoutable:finalLayoutable]; + } + } else { + _children.erase(0); + } } - (void)setChild:(id)child forIndex:(NSUInteger)index @@ -133,16 +134,11 @@ ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); if (child) { id finalLayoutable = [self layoutableToAddFromLayoutable:child]; - if (finalLayoutable) { - _childrenMap[index] = finalLayoutable; - [self propagateUpLayoutable:finalLayoutable]; - } + _children[index] = finalLayoutable; } else { - _childrenMap.erase(index); + _children.erase(index); } - _mutations++; - - // TODO: Should we propagate up the layoutable as it could happen that multiple children will propagated up their + // TODO: Should we propagate up the layoutable at it could happen that multiple children will propagated up their // layout options and one child will overwrite values from another child // [self propagateUpLayoutable:finalLayoutable]; } @@ -151,73 +147,37 @@ { ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable"); - _childrenMap.clear(); + _children.clear(); NSUInteger i = 0; for (id child in children) { - _childrenMap[i] = [self layoutableToAddFromLayoutable:child]; + _children[i] = [self layoutableToAddFromLayoutable:child]; i += 1; - - _mutations++; } } - (id)childForIndex:(NSUInteger)index { - if (index < _childrenMap.size()) { - return _childrenMap[index]; + if (index < _children.size()) { + return _children[index]; } return nil; } - (id)child { - return _childrenMap[0]; + return _children[0]; } - (NSArray *)children { - // If used inside ASDK, the childrenMap property should be preferred over the children array to prevent - // unecessary boxing std::vector children; - for (auto const &entry : _childrenMap) { - children.push_back(entry.second); + for (ASChildMap::iterator it = _children.begin(); it != _children.end(); ++it ) { + children.push_back(it->second); } - + return [NSArray arrayWithObjects:&children[0] count:children.size()]; } -#pragma mark - NSFastEnumeration - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state - objects:(id __unsafe_unretained [])stackbuf - count:(NSUInteger)stackbufLength -{ - NSUInteger count = 0; - unsigned long countOfItemsAlreadyEnumerated = state->state; - - if (countOfItemsAlreadyEnumerated == 0) { - state->mutationsPtr = &_mutations; - } - - if (countOfItemsAlreadyEnumerated < _childrenMap.size()) { - state->itemsPtr = stackbuf; - - while((countOfItemsAlreadyEnumerated < _childrenMap.size()) && (count < stackbufLength)) { - // Hold on for the object while enumerating - __autoreleasing id child = _childrenMap[countOfItemsAlreadyEnumerated]; - stackbuf[count] = child; - countOfItemsAlreadyEnumerated++; - count++; - } - } else { - count = 0; - } - - state->state = countOfItemsAlreadyEnumerated; - - return count; -} - #pragma mark - ASEnvironment - (ASEnvironmentState)environmentState @@ -273,15 +233,6 @@ ASEnvironmentLayoutExtensibilityForwarding @end -@implementation ASLayoutSpec (Private) - -- (ASChildrenMap)childrenMap -{ - return _childrenMap; -} - -@end - @implementation ASLayoutSpec (Debugging) #pragma mark - ASLayoutableAsciiArtProtocol diff --git a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm index a6ab9d3fea..2393972a53 100644 --- a/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStackLayoutSpec.mm @@ -13,7 +13,6 @@ #import "ASInternalHelpers.h" -#import "ASLayoutSpec+Private.h" #import "ASLayoutSpecUtilities.h" #import "ASStackBaselinePositionedLayout.h" #import "ASThread.h" @@ -59,7 +58,7 @@ _alignItems = alignItems; _justifyContent = justifyContent; - self.children = children; + [self setChildren:children]; return self; } @@ -121,9 +120,7 @@ - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize { - auto const &children = self.childrenMap; - - if (children.size() == 0) { + if (self.children.count == 0) { return [ASLayout layoutWithLayoutableObject:self constrainedSizeRange:constrainedSize size:constrainedSize.min]; @@ -132,9 +129,9 @@ ASStackLayoutSpecStyle style = {.direction = _direction, .spacing = _spacing, .justifyContent = _justifyContent, .alignItems = _alignItems, .baselineRelativeArrangement = _baselineRelativeArrangement}; BOOL needsBaselinePass = _baselineRelativeArrangement || _alignItems == ASStackLayoutAlignItemsBaselineFirst || _alignItems == ASStackLayoutAlignItemsBaselineLast; - std::vector> stackChildren; - for (auto const &entry : children) { - stackChildren.push_back(entry.second); + std::vector> stackChildren = std::vector>(); + for (id child in self.children) { + stackChildren.push_back(child); } const auto unpositionedLayout = ASStackUnpositionedLayout::compute(stackChildren, style, constrainedSize); @@ -146,18 +143,14 @@ // regardless of whether or not this stack aligns to baseline, we should let ASStackBaselinePositionedLayout::compute find the max ascender // and min descender in case this spec is a child in another spec that wants to align to a baseline. const auto baselinePositionedLayout = ASStackBaselinePositionedLayout::compute(positionedLayout, style, constrainedSize); - { + if (self.direction == ASStackLayoutDirectionVertical) { ASDN::MutexLocker l(__instanceLock__); - if (self.direction == ASStackLayoutDirectionVertical) { - if (stackChildren.size() > 0) { - self.ascender = stackChildren.front().ascender; - self.descender = stackChildren.back().descender; - } - - } else { - self.ascender = baselinePositionedLayout.ascender; - self.descender = baselinePositionedLayout.descender; - } + self.ascender = [[self.children firstObject] ascender]; + self.descender = [[self.children lastObject] descender]; + } else { + ASDN::MutexLocker l(__instanceLock__); + self.ascender = baselinePositionedLayout.ascender; + self.descender = baselinePositionedLayout.descender; } if (needsBaselinePass) { diff --git a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm index 86ca74908d..516e79e721 100644 --- a/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm +++ b/AsyncDisplayKit/Layout/ASStaticLayoutSpec.mm @@ -10,7 +10,6 @@ #import "ASStaticLayoutSpec.h" -#import "ASLayoutSpec+Private.h" #import "ASLayoutSpecUtilities.h" #import "ASLayout.h" @@ -39,8 +38,10 @@ { CGSize maxConstrainedSize = CGSizeMake(constrainedSize.max.width, constrainedSize.max.height); - NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:self.childrenMap.size()]; - for (id child in self) { + NSArray *children = self.children; + NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:children.count]; + + for (id child in children) { CGPoint layoutPosition = child.layoutPosition; CGSize autoMaxSize = CGSizeMake(maxConstrainedSize.width - layoutPosition.x, maxConstrainedSize.height - layoutPosition.y); diff --git a/AsyncDisplayKit/Private/ASEnvironmentInternal.mm b/AsyncDisplayKit/Private/ASEnvironmentInternal.mm index 05b6ad894d..5a3c88b784 100644 --- a/AsyncDisplayKit/Private/ASEnvironmentInternal.mm +++ b/AsyncDisplayKit/Private/ASEnvironmentInternal.mm @@ -44,7 +44,7 @@ void ASEnvironmentPerformBlockOnObjectAndChildren(id object, void block(object); - for (id child in object) { + for (id child in [object children]) { queue.push(child); } } diff --git a/AsyncDisplayKit/Private/ASLayoutSpec+Private.h b/AsyncDisplayKit/Private/ASLayoutSpec+Private.h deleted file mode 100644 index 0ba0390ee8..0000000000 --- a/AsyncDisplayKit/Private/ASLayoutSpec+Private.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// ASLayoutSpec+Private.h -// AsyncDisplayKit -// -// Copyright (c) 2014-present, Facebook, Inc. All rights reserved. -// This source code is licensed under the BSD-style license found in the -// LICENSE file in the root directory of this source tree. An additional grant -// of patent rights can be found in the PATENTS file in the same directory. -// - -#import "ASLayoutSpec.h" - -#import -#import - -typedef std::map, std::less> ASChildrenMap; - -@interface ASLayoutSpec (Private) - -/* - * Inside ASDK the childrenMap property should be preferred over the children array to prevent unecessary boxing - */ -@property (nonatomic, assign, readonly) ASChildrenMap childrenMap; - -@end diff --git a/AsyncDisplayKitTests/ASDisplayNodeTests.m b/AsyncDisplayKitTests/ASDisplayNodeTests.m index 88b96a665c..9be86b49de 100644 --- a/AsyncDisplayKitTests/ASDisplayNodeTests.m +++ b/AsyncDisplayKitTests/ASDisplayNodeTests.m @@ -1723,24 +1723,6 @@ static inline BOOL _CGPointEqualToPointWithEpsilon(CGPoint point1, CGPoint point XCTAssertEqual(1, view.subviews.count, @"View should have 1 subview"); } -- (void)testFastEnumeration -{ - ASDisplayNode *parent = [[ASDisplayNode alloc] init]; - - NSMutableArray *children = [NSMutableArray array]; - for (int i = 0; i < 100; i++) { - ASDisplayNode *child = [[[ASDisplayNode alloc] init] autorelease]; - [children addObject:child]; - [parent addSubnode:child]; - } - - NSInteger i = 0; - for (ASDisplayNode *child in parent) { - XCTAssertEqualObjects(child, children[i]); - i++; - } -} - - (void)checkBackgroundColorOpaqueRelationshipWithViewLoaded:(BOOL)loaded layerBacked:(BOOL)isLayerBacked { ASDisplayNode *node = [[ASDisplayNode alloc] init]; diff --git a/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m b/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m index 31801fb2b2..bb182aa4a7 100644 --- a/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m +++ b/AsyncDisplayKitTests/ASLayoutSpecSnapshotTestsHelper.m @@ -42,23 +42,6 @@ ASSnapshotVerifyNode(node, identifier); } -- (void)testFastEnumeration -{ - ASLayoutSpec *layoutSpec = [[ASLayoutSpec alloc] init]; - - NSMutableArray *children = [NSMutableArray array]; - for (int i = 0; i < 100; i++) { - [children addObject:[[ASDisplayNode alloc] init]]; - } - layoutSpec.children = children; - - NSInteger i = 0; - for (ASDisplayNode *child in layoutSpec) { - XCTAssertEqualObjects(child, children[i]); - i++; - } -} - @end @implementation ASTestNode