diff --git a/AsyncDisplayKit/ASDisplayNode+Subclasses.h b/AsyncDisplayKit/ASDisplayNode+Subclasses.h index e369b5c18a..023567d9a2 100644 --- a/AsyncDisplayKit/ASDisplayNode+Subclasses.h +++ b/AsyncDisplayKit/ASDisplayNode+Subclasses.h @@ -206,6 +206,8 @@ NS_ASSUME_NONNULL_BEGIN * * @discussion Subclasses may override this method to be notified when display (asynchronous or synchronous) is * about to begin. + * + * @note Called on the main thread only */ - (void)displayWillStart ASDISPLAYNODE_REQUIRES_SUPER; @@ -214,6 +216,8 @@ NS_ASSUME_NONNULL_BEGIN * * @discussion Subclasses may override this method to be notified when display (asynchronous or synchronous) has * completed. + * + * @note Called on the main thread only */ - (void)displayDidFinish ASDISPLAYNODE_REQUIRES_SUPER; diff --git a/AsyncDisplayKit/ASDisplayNode.mm b/AsyncDisplayKit/ASDisplayNode.mm index d16479a5d5..256e9e7d03 100644 --- a/AsyncDisplayKit/ASDisplayNode.mm +++ b/AsyncDisplayKit/ASDisplayNode.mm @@ -1657,7 +1657,7 @@ static NSInteger incrementIfFound(NSInteger i) { // The node sending the message should usually be passed as the parameter, similar to the delegation pattern. - (void)_pendingNodeWillDisplay:(ASDisplayNode *)node { - ASDN::MutexLocker l(_propertyLock); + ASDisplayNodeAssertMainThread(); if (!_pendingDisplayNodes) { _pendingDisplayNodes = [[NSMutableSet alloc] init]; @@ -1670,27 +1670,25 @@ static NSInteger incrementIfFound(NSInteger i) { // The node sending the message should usually be passed as the parameter, similar to the delegation pattern. - (void)_pendingNodeDidDisplay:(ASDisplayNode *)node { - ASDN::MutexLocker l(_propertyLock); + ASDisplayNodeAssertMainThread(); [_pendingDisplayNodes removeObject:node]; // only trampoline if there is a placeholder and nodes are done displaying if ([self _pendingDisplayNodesHaveFinished] && _placeholderLayer.superlayer) { - dispatch_async(dispatch_get_main_queue(), ^{ - void (^cleanupBlock)() = ^{ - [self _tearDownPlaceholderLayer]; - }; + void (^cleanupBlock)() = ^{ + [self _tearDownPlaceholderLayer]; + }; - if (_placeholderFadeDuration > 0.0 && ASInterfaceStateIncludesVisible(self.interfaceState)) { - [CATransaction begin]; - [CATransaction setCompletionBlock:cleanupBlock]; - [CATransaction setAnimationDuration:_placeholderFadeDuration]; - _placeholderLayer.opacity = 0.0; - [CATransaction commit]; - } else { - cleanupBlock(); - } - }); + if (_placeholderFadeDuration > 0.0 && ASInterfaceStateIncludesVisible(self.interfaceState)) { + [CATransaction begin]; + [CATransaction setCompletionBlock:cleanupBlock]; + [CATransaction setAnimationDuration:_placeholderFadeDuration]; + _placeholderLayer.opacity = 0.0; + [CATransaction commit]; + } else { + cleanupBlock(); + } } } @@ -2260,6 +2258,8 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) - (void)displayWillStart { + ASDisplayNodeAssertMainThread(); + // in case current node takes longer to display than it's subnodes, treat it as a dependent node [self _pendingNodeWillDisplay:self]; @@ -2288,6 +2288,8 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock) - (void)displayDidFinish { + ASDisplayNodeAssertMainThread(); + [self _pendingNodeDidDisplay:self]; [_supernode subnodeDisplayDidFinish:self]; @@ -2494,11 +2496,14 @@ static void _recursivelySetDisplaySuspended(ASDisplayNode *node, CALayer *layer, self.asyncLayer.displaySuspended = flag; if ([self __implementsDisplay]) { - if (flag) { - [_supernode subnodeDisplayDidFinish:self]; - } else { - [_supernode subnodeDisplayWillStart:self]; - } + // Display start and finish methods needs to happen on the main thread + ASPerformBlockOnMainThread(^{ + if (flag) { + [_supernode subnodeDisplayDidFinish:self]; + } else { + [_supernode subnodeDisplayWillStart:self]; + } + }); } }