From 377aeebde4373fcc5f172167df5cfabe393e82df Mon Sep 17 00:00:00 2001 From: Tim Norman Date: Fri, 12 Apr 2019 12:13:43 -0700 Subject: [PATCH] Add didEnterHierarchy/didExitHierarchy to ASNodeController. (#1444) --- Source/ASDisplayNode+InterfaceState.h | 18 ++++++++++++++++++ Source/ASDisplayNode.mm | 12 ++++++++++++ Source/ASNodeController+Beta.h | 3 +++ Source/ASNodeController+Beta.mm | 3 +++ 4 files changed, 36 insertions(+) diff --git a/Source/ASDisplayNode+InterfaceState.h b/Source/ASDisplayNode+InterfaceState.h index 1de83700a..a9025df71 100644 --- a/Source/ASDisplayNode+InterfaceState.h +++ b/Source/ASDisplayNode+InterfaceState.h @@ -127,4 +127,22 @@ typedef NS_OPTIONS(NSUInteger, ASInterfaceState) */ - (void)nodeWillCalculateLayout:(ASSizeRange)constrainedSize; +/** + * @abstract Called when the node's layer is about to enter the hierarchy. + * @discussion May be called more than once if the layer is participating in a higher-level + * animation, such as a UIViewController transition. These animations can cause the layer to get + * re-parented multiple times, and each time will trigger this call. + * @note This method is guaranteed to be called on main. + */ +- (void)didEnterHierarchy; + +/** + * @abstract Called when the node's layer has exited the hierarchy. + * @discussion May be called more than once if the layer is participating in a higher-level + * animation, such as a UIViewController transition. These animations can cause the layer to get + * re-parented multiple times, and each time will trigger this call. + * @note This method is guaranteed to be called on main. + */ +- (void)didExitHierarchy; + @end diff --git a/Source/ASDisplayNode.mm b/Source/ASDisplayNode.mm index cb1b3c68b..458941b97 100644 --- a/Source/ASDisplayNode.mm +++ b/Source/ASDisplayNode.mm @@ -2874,6 +2874,12 @@ - (void)didEnterHierarchy { ASDisplayNodeAssert(!_flags.isExitingHierarchy, @"ASDisplayNode inconsistency. __enterHierarchy and __exitHierarchy are mutually exclusive"); ASDisplayNodeAssert(_flags.isInHierarchy, @"ASDisplayNode inconsistency. __enterHierarchy and __exitHierarchy are mutually exclusive"); ASAssertUnlocked(__instanceLock__); + + [self enumerateInterfaceStateDelegates:^(id del) { + if ([del respondsToSelector:@selector(didEnterHierarchy)]) { + [del didEnterHierarchy]; + } + }]; } - (void)didExitHierarchy @@ -2883,6 +2889,12 @@ - (void)didExitHierarchy ASDisplayNodeAssert(!_flags.isEnteringHierarchy, @"ASDisplayNode inconsistency. __enterHierarchy and __exitHierarchy are mutually exclusive"); ASAssertUnlocked(__instanceLock__); + [self enumerateInterfaceStateDelegates:^(id del) { + if ([del respondsToSelector:@selector(didExitHierarchy)]) { + [del didExitHierarchy]; + } + }]; + // This case is important when tearing down hierarchies. We must deliver a visibileStateDidChange:NO callback, as part our API guarantee that this method can be used for // things like data analytics about user content viewing. We cannot call the method in the dealloc as any incidental retain operations in client code would fail. // Additionally, it may be that a Standard UIView which is containing us is moving between hierarchies, and we should not send the call if we will be re-added in the diff --git a/Source/ASNodeController+Beta.h b/Source/ASNodeController+Beta.h index e9028f198..6501a114a 100644 --- a/Source/ASNodeController+Beta.h +++ b/Source/ASNodeController+Beta.h @@ -44,6 +44,9 @@ - (void)hierarchyDisplayDidFinish ASDISPLAYNODE_REQUIRES_SUPER; +- (void)didEnterHierarchy ASDISPLAYNODE_REQUIRES_SUPER; +- (void)didExitHierarchy ASDISPLAYNODE_REQUIRES_SUPER; + /** * @discussion Attempts (via ASLockSequence, a backing-off spinlock similar to * std::lock()) to lock both the node and its ASNodeController, if one exists. diff --git a/Source/ASNodeController+Beta.mm b/Source/ASNodeController+Beta.mm index 14aae3363..34ea73544 100644 --- a/Source/ASNodeController+Beta.mm +++ b/Source/ASNodeController+Beta.mm @@ -92,6 +92,9 @@ - (void)interfaceStateDidChange:(ASInterfaceState)newState - (void)hierarchyDisplayDidFinish {} +- (void)didEnterHierarchy {} +- (void)didExitHierarchy {} + - (ASLockSet)lockPair { ASLockSet lockSet = ASLockSequence(^BOOL(ASAddLockBlock addLock) { if (!addLock(_node)) {