From 90e97d9d80fc22666e7c52b29ae2ddf9672a3cc9 Mon Sep 17 00:00:00 2001 From: Max Wang Date: Fri, 31 Aug 2018 13:16:55 -0700 Subject: [PATCH] Allow to add interface state delegate in background. (#1090) * fix SIMULATE_WEB_RESPONSE not imported #449 * Fix to make rangeMode update in right time * remove uncessary assert * Allow to add interface state delegate in background threads. * Allow to add interface state delegate in background threads. * lock around _interfaceStateDelegates * lock _interfaceStateDelegates to local variable * Fix comments * remove extra spaces --- CHANGELOG.md | 1 + Source/ASDisplayNode.mm | 77 +++++++++++++---------------------------- 2 files changed, 26 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d41a74f20..53ae274b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ ## master * Add your own contributions to the next release on the line below this with your name. +- [ASDisplayNode] Allow add/remove interface state delegates on background thread. [Max Wang](https://github.com/wsdwsd0829). [#1090](https://github.com/TextureGroup/Texture/pull/1090) - [License] Simplify the Texture license to be pure Apache 2 (removing ASDK-Licenses).[Scott Goodson](https://github.com/appleguy) [#1077](https://github.com/TextureGroup/Texture/pull/1077) - [ASNetworkImageNode] Allow delegate methods to be called on background thread. [Max Wang](https://github.com/wsdwsd0829). [#1007](https://github.com/TextureGroup/Texture/pull/1007) - [ASLayoutTransition] Add support for preserving order after node moves during transitions. (This order defines the z-order as well.) [Kevin Smith](https://github.com/wiseoldduck) [#1006] diff --git a/Source/ASDisplayNode.mm b/Source/ASDisplayNode.mm index f24a9cb28..3631bd522 100644 --- a/Source/ASDisplayNode.mm +++ b/Source/ASDisplayNode.mm @@ -452,6 +452,16 @@ - (void)dealloc #pragma mark - Loading +#define ASDisplayNodeCallInterfaceStateDelegates(method) \ + __instanceLock__.lock(); \ + NSHashTable *delegates = [_interfaceStateDelegates copy]; \ + __instanceLock__.unlock(); \ + for (id delegate in delegates) { \ + if ([delegate respondsToSelector:@selector(method)]) { \ + [delegate method]; \ + } \ + } + - (BOOL)_locked_shouldLoadViewOrLayer { ASAssertLocked(__instanceLock__); @@ -564,12 +574,7 @@ - (void)_didLoad for (ASDisplayNodeDidLoadBlock block in onDidLoadBlocks) { block(self); } - - for (id delegate in _interfaceStateDelegates) { - if ([delegate respondsToSelector:@selector(nodeDidLoad)]) { - [delegate nodeDidLoad]; - } - } + ASDisplayNodeCallInterfaceStateDelegates(nodeDidLoad); } - (void)didLoad @@ -1274,11 +1279,7 @@ - (void)layout ASDisplayNodeAssertMainThread(); ASAssertUnlocked(__instanceLock__); ASDisplayNodeAssertTrue(self.isNodeLoaded); - for (id delegate in _interfaceStateDelegates) { - if ([delegate respondsToSelector:@selector(nodeDidLayout)]) { - [delegate nodeDidLayout]; - } - } + ASDisplayNodeCallInterfaceStateDelegates(nodeDidLayout); } #pragma mark Layout Transition @@ -1501,12 +1502,7 @@ - (void)_pendingNodeDidDisplay:(ASDisplayNode *)node if (_pendingDisplayNodes.isEmpty) { [self hierarchyDisplayDidFinish]; - - for (id delegate in _interfaceStateDelegates) { - if ([delegate respondsToSelector:@selector(hierarchyDisplayDidFinish)]) { - [delegate hierarchyDisplayDidFinish]; - } - } + ASDisplayNodeCallInterfaceStateDelegates(hierarchyDisplayDidFinish); BOOL placeholderShouldPersist = [self placeholderShouldPersist]; @@ -3217,7 +3213,10 @@ - (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfac // Subclass hook ASAssertUnlocked(__instanceLock__); ASDisplayNodeAssertMainThread(); - for (id delegate in _interfaceStateDelegates) { + __instanceLock__.lock(); + NSHashTable *delegates = [_interfaceStateDelegates copy]; + __instanceLock__.unlock(); + for (id delegate in delegates) { if ([delegate respondsToSelector:@selector(interfaceStateDidChange:fromState:)]) { [delegate interfaceStateDidChange:newState fromState:oldState]; } @@ -3233,8 +3232,7 @@ - (BOOL)shouldScheduleDisplayWithNewInterfaceState:(ASInterfaceState)newInterfac - (void)addInterfaceStateDelegate:(id )interfaceStateDelegate { - ASDisplayNodeAssertMainThread(); - + ASDN::MutexLocker l(__instanceLock__); // Not a fan of lazy loading, but this method won't get called very often and avoiding // the overhead of creating this is probably worth it. if (_interfaceStateDelegates == nil) { @@ -3245,7 +3243,7 @@ - (void)addInterfaceStateDelegate:(id )interfaceStateD - (void)removeInterfaceStateDelegate:(id )interfaceStateDelegate { - ASDisplayNodeAssertMainThread(); + ASDN::MutexLocker l(__instanceLock__); [_interfaceStateDelegates removeObject:interfaceStateDelegate]; } @@ -3260,11 +3258,7 @@ - (void)didEnterVisibleState // subclass override ASDisplayNodeAssertMainThread(); ASAssertUnlocked(__instanceLock__); - for (id delegate in _interfaceStateDelegates) { - if ([delegate respondsToSelector:@selector(didEnterVisibleState)]) { - [delegate didEnterVisibleState]; - } - } + ASDisplayNodeCallInterfaceStateDelegates(didEnterVisibleState); #if AS_ENABLE_TIPS [ASTipsController.shared nodeDidAppear:self]; #endif @@ -3275,11 +3269,7 @@ - (void)didExitVisibleState // subclass override ASDisplayNodeAssertMainThread(); ASAssertUnlocked(__instanceLock__); - for (id delegate in _interfaceStateDelegates) { - if ([delegate respondsToSelector:@selector(didExitVisibleState)]) { - [delegate didExitVisibleState]; - } - } + ASDisplayNodeCallInterfaceStateDelegates(didExitVisibleState); } - (BOOL)isInDisplayState @@ -3293,11 +3283,7 @@ - (void)didEnterDisplayState // subclass override ASDisplayNodeAssertMainThread(); ASAssertUnlocked(__instanceLock__); - for (id delegate in _interfaceStateDelegates) { - if ([delegate respondsToSelector:@selector(didEnterDisplayState)]) { - [delegate didEnterDisplayState]; - } - } + ASDisplayNodeCallInterfaceStateDelegates(didEnterDisplayState); } - (void)didExitDisplayState @@ -3305,11 +3291,7 @@ - (void)didExitDisplayState // subclass override ASDisplayNodeAssertMainThread(); ASAssertUnlocked(__instanceLock__); - for (id delegate in _interfaceStateDelegates) { - if ([delegate respondsToSelector:@selector(didExitDisplayState)]) { - [delegate didExitDisplayState]; - } - } + ASDisplayNodeCallInterfaceStateDelegates(didExitDisplayState); } - (BOOL)isInPreloadState @@ -3359,23 +3341,14 @@ - (void)didEnterPreloadState if (self.automaticallyManagesSubnodes) { [self layoutIfNeeded]; } - - for (id delegate in _interfaceStateDelegates) { - if ([delegate respondsToSelector:@selector(didEnterPreloadState)]) { - [delegate didEnterPreloadState]; - } - } + ASDisplayNodeCallInterfaceStateDelegates(didEnterPreloadState); } - (void)didExitPreloadState { ASDisplayNodeAssertMainThread(); ASAssertUnlocked(__instanceLock__); - for (id delegate in _interfaceStateDelegates) { - if ([delegate respondsToSelector:@selector(didExitPreloadState)]) { - [delegate didExitPreloadState]; - } - } + ASDisplayNodeCallInterfaceStateDelegates(didExitPreloadState); } - (void)clearContents