Merge pull request #1304 from garrettmoon/betterSkipClearContents

[ASDisplayNode] Coalesce -clearContents onto the next runloop, so it can be skipped if re-added to hierarchy in move operation.
This commit is contained in:
appleguy 2016-03-01 17:38:36 -08:00
commit 47d2981487
2 changed files with 17 additions and 26 deletions

View File

@ -1227,7 +1227,7 @@ static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASD
if (isMovingEquivalentParents) { if (isMovingEquivalentParents) {
[subnode __incrementVisibilityNotificationsDisabled]; [subnode __incrementVisibilityNotificationsDisabled];
} }
[subnode removeFromSupernodeMovingBetweenNodes:YES]; [subnode removeFromSupernode];
if (!_subnodes) if (!_subnodes)
_subnodes = [[NSMutableArray alloc] init]; _subnodes = [[NSMutableArray alloc] init];
@ -1497,11 +1497,6 @@ static NSInteger incrementIfFound(NSInteger i) {
} }
- (void)removeFromSupernode - (void)removeFromSupernode
{
[self removeFromSupernodeMovingBetweenNodes:NO];
}
- (void)removeFromSupernodeMovingBetweenNodes:(BOOL)movingBetweenNodes
{ {
ASDisplayNodeAssertThreadAffinity(self); ASDisplayNodeAssertThreadAffinity(self);
BOOL shouldRemoveFromSuperviewOrSuperlayer = NO; BOOL shouldRemoveFromSuperviewOrSuperlayer = NO;
@ -1510,7 +1505,7 @@ static NSInteger incrementIfFound(NSInteger i) {
ASDN::MutexLocker l(_propertyLock); ASDN::MutexLocker l(_propertyLock);
if (!_supernode) if (!_supernode)
return; return;
// Check to ensure that our view or layer is actually inside of our supernode; otherwise, don't remove it. // Check to ensure that our view or layer is actually inside of our supernode; otherwise, don't remove it.
// Though _ASDisplayView decouples the supernode if it is inserted inside another view hierarchy, this is // Though _ASDisplayView decouples the supernode if it is inserted inside another view hierarchy, this is
// more difficult to guarantee with _ASDisplayLayer because CoreAnimation doesn't have a -didMoveToSuperlayer. // more difficult to guarantee with _ASDisplayLayer because CoreAnimation doesn't have a -didMoveToSuperlayer.
@ -1527,22 +1522,15 @@ static NSInteger incrementIfFound(NSInteger i) {
// Do this before removing the view from the hierarchy, as the node will clear its supernode pointer when its view is removed from the hierarchy. // Do this before removing the view from the hierarchy, as the node will clear its supernode pointer when its view is removed from the hierarchy.
// This call may result in the object being destroyed. // This call may result in the object being destroyed.
[_supernode _removeSubnode:self]; [_supernode _removeSubnode:self];
if (shouldRemoveFromSuperviewOrSuperlayer) { if (shouldRemoveFromSuperviewOrSuperlayer) {
ASPerformBlockOnMainThread(^{ ASPerformBlockOnMainThread(^{
ASDN::MutexLocker l(_propertyLock); ASDN::MutexLocker l(_propertyLock);
if (movingBetweenNodes) {
_flags.isMovingBetweenNodes = YES;
}
if (_flags.layerBacked) { if (_flags.layerBacked) {
[_layer removeFromSuperlayer]; [_layer removeFromSuperlayer];
} else { } else {
[_view removeFromSuperview]; [_view removeFromSuperview];
} }
if (movingBetweenNodes) {
_flags.isMovingBetweenNodes = NO;
}
}); });
} }
} }
@ -1982,14 +1970,6 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
- (void)clearContents - (void)clearContents
{ {
// No-op if these haven't been created yet, as that guarantees they don't have contents that needs to be released. // No-op if these haven't been created yet, as that guarantees they don't have contents that needs to be released.
{
ASDN::MutexLocker l(_propertyLock);
//Do not clear contents if we're mearly moving between nodes
if (_flags.isMovingBetweenNodes) {
return;
}
}
_layer.contents = nil; _layer.contents = nil;
_placeholderLayer.contents = nil; _placeholderLayer.contents = nil;
_placeholderImage = nil; _placeholderImage = nil;
@ -2103,7 +2083,13 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
[self setDisplaySuspended:NO]; [self setDisplaySuspended:NO];
} else { } else {
[self setDisplaySuspended:YES]; [self setDisplaySuspended:YES];
[self clearContents]; //schedule clear contents on next runloop
dispatch_async(dispatch_get_main_queue(), ^{
ASDN::MutexLocker l(_propertyLock);
if (ASInterfaceStateIncludesDisplay(_interfaceState) == NO) {
[self clearContents];
}
});
} }
} else { } else {
// NOTE: This case isn't currently supported as setInterfaceState: isn't exposed externally, and all // NOTE: This case isn't currently supported as setInterfaceState: isn't exposed externally, and all
@ -2115,7 +2101,13 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
[ASDisplayNode scheduleNodeForRecursiveDisplay:self]; [ASDisplayNode scheduleNodeForRecursiveDisplay:self];
} else { } else {
[[self asyncLayer] cancelAsyncDisplay]; [[self asyncLayer] cancelAsyncDisplay];
[self clearContents]; //schedule clear contents on next runloop
dispatch_async(dispatch_get_main_queue(), ^{
ASDN::MutexLocker l(_propertyLock);
if (ASInterfaceStateIncludesDisplay(_interfaceState) == NO) {
[self clearContents];
}
});
} }
} }
} }

View File

@ -82,7 +82,6 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
unsigned isEnteringHierarchy:1; unsigned isEnteringHierarchy:1;
unsigned isExitingHierarchy:1; unsigned isExitingHierarchy:1;
unsigned isInHierarchy:1; unsigned isInHierarchy:1;
unsigned isMovingBetweenNodes:1;
unsigned visibilityNotificationsDisabled:VISIBILITY_NOTIFICATIONS_DISABLED_BITS; unsigned visibilityNotificationsDisabled:VISIBILITY_NOTIFICATIONS_DISABLED_BITS;
} _flags; } _flags;