From 997d37dc83feeb03d2fccda76a8bec4b2c92bbc5 Mon Sep 17 00:00:00 2001 From: ricky Date: Thu, 23 Jun 2016 20:07:45 -0700 Subject: [PATCH] [ASEnvironment] Don't relayout as a result of clearing a traitCollection's context (#1759) * Don't relayout as a result of clearing a traitCollection's context I'm not completely sure this change is the best solution. Here is context: An ASEnvironmentTraitCollection has a pointer to an optional context that an ASVC is the owner of. When the ASVC is dealloc'ed, we go through all subnodes of the VC and clear out the context so that the struct isn't holding on to a garbage pointer. Setting the traitCollection on ASCollectionNode/ASTableNode causes the cells to relayout if the trait collection changed (this is a special case for these two nodes since their cells are not actually subnodes). Setting the context to nil registered as a trait collection change and was causing a layout even as we were dealloc'ing the VC. The logic I'm implementing here is: If the trait collection changed AND the displayContext did not, then we should relayout. If the trait collection changed AND the new displayContext is non-nil then we should layout In the case where the trait collection change was caused soley by the displayContext going from non-nil to nil, then we should NOT layout. ``` // At this point we know that the two traits collections are NOT equal for some reason BOOL needsLayout = (oldTraits.displayContext == currentTraits.displayContext) || currentTraits.displayContext != nil; ``` Is there a better place/safer way to do this? * removed extra setNeedsLayout call --- AsyncDisplayKit/Details/ASEnvironment.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/AsyncDisplayKit/Details/ASEnvironment.h b/AsyncDisplayKit/Details/ASEnvironment.h index 6c395aa18e..e267de1e8a 100644 --- a/AsyncDisplayKit/Details/ASEnvironment.h +++ b/AsyncDisplayKit/Details/ASEnvironment.h @@ -147,6 +147,9 @@ ASDISPLAYNODE_EXTERN_C_END // // If there is any new downward propagating state, it should be added to this define. // +// If the only change in a trait collection is that its dislplayContext has gone from non-nil to nil, +// assume that we are clearing the context as part of a ASVC dealloc and do not trigger a layout. +// // This logic is used in both ASCollectionNode and ASTableNode #define ASEnvironmentCollectionTableSetEnvironmentState(lock) \ - (void)setEnvironmentState:(ASEnvironmentState)environmentState\ @@ -156,12 +159,16 @@ ASDISPLAYNODE_EXTERN_C_END [super setEnvironmentState:environmentState];\ ASEnvironmentTraitCollection currentTraits = environmentState.environmentTraitCollection;\ if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(currentTraits, oldTraits) == NO) {\ + /* Must dispatch to main for self.view && [self.view.dataController completedNodes]*/ \ ASPerformBlockOnMainThread(^{\ + BOOL needsLayout = (oldTraits.displayContext == currentTraits.displayContext) || currentTraits.displayContext != nil;\ NSArray *> *completedNodes = [self.view.dataController completedNodes];\ for (NSArray *sectionArray in completedNodes) {\ for (ASCellNode *cellNode in sectionArray) {\ ASEnvironmentStatePropagateDown(cellNode, currentTraits);\ - [cellNode setNeedsLayout];\ + if (needsLayout) {\ + [cellNode setNeedsLayout];\ + }\ }\ }\ });\