From 9e76d7b603f0b82612344ca96e6e051ebcf75836 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Sun, 20 Mar 2016 23:14:53 -0700 Subject: [PATCH] Add method to cancel layout transitions in progress - Also make sure a transition isn't invalidated right after it passed the validation test and before it proceeds --- AsyncDisplayKit/ASDisplayNode+Beta.h | 5 +++++ AsyncDisplayKit/ASDisplayNode.mm | 28 ++++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/AsyncDisplayKit/ASDisplayNode+Beta.h b/AsyncDisplayKit/ASDisplayNode+Beta.h index 11cd6d0e70..4bb108b66a 100644 --- a/AsyncDisplayKit/ASDisplayNode+Beta.h +++ b/AsyncDisplayKit/ASDisplayNode+Beta.h @@ -98,4 +98,9 @@ ASDISPLAYNODE_EXTERN_C_END */ - (BOOL)placeholderShouldPersist; +/** + * @abstract Cancels all performing layout transitions. Can be called on any thread. + */ +- (void)cancelLayoutTransitionsInProgress; + @end diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index 0596eaf510..f1b6aa26f2 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -593,14 +593,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) return _layout; } - if ([self _hasTransitionsInProgress]) { - // Invalidate transition sentinel to cancel transitions in progress - [self _invalidateTransitionSentinel]; - // Tell subnodes to exit layout pending state and clear related properties - ASDisplayNodePerformBlockOnEverySubnode(self, ^(ASDisplayNode * _Nonnull node) { - node.hierarchyState &= (~ASHierarchyStateLayoutPending); - }); - } + [self cancelLayoutTransitionsInProgress]; ASLayout *previousLayout = _layout; ASSizeRange previousConstrainedSize = _constrainedSize; @@ -698,12 +691,14 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) } ASPerformBlockOnMainThread(^{ + // Grab _propertyLock here to make sure this transition isn't invalidated + // right after it passed the validation test and before it proceeds + ASDN::MutexLocker l(_propertyLock); + if ([self _shouldAbortTransitionWithID:transitionID]) { return; } - ASDN::MutexLocker l(_propertyLock); - ASLayout *previousLayout = _layout; ASSizeRange previousConstrainedSize = _constrainedSize; [self applyLayout:newLayout constrainedSize:constrainedSize layoutContext:nil]; @@ -769,6 +764,19 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c) // subclass override } +- (void)cancelLayoutTransitionsInProgress +{ + ASDN::MutexLocker l(_propertyLock); + if ([self _hasTransitionsInProgress]) { + // Invalidate transition sentinel to cancel transitions in progress + [self _invalidateTransitionSentinel]; + // Tell subnodes to exit layout pending state and clear related properties + ASDisplayNodePerformBlockOnEverySubnode(self, ^(ASDisplayNode * _Nonnull node) { + node.hierarchyState &= (~ASHierarchyStateLayoutPending); + }); + } +} + #pragma mark - Layout Transition - (BOOL)usesImplicitHierarchyManagement