Skip to content
This repository was archived by the owner on Feb 2, 2023. It is now read-only.

Commit d7492b3

Browse files
committed
Merge pull request #968 from facebook/LockHandlingOnRemoveFromSupernode
[ASDisplayNode] Release the lock before setting supernode pointer to nil, in case we are deallocated.
2 parents af9f8df + 06688f7 commit d7492b3

1 file changed

Lines changed: 19 additions & 14 deletions

File tree

AsyncDisplayKit/ASDisplayNode.mm

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,28 +1217,33 @@ - (void)_removeSubnode:(ASDisplayNode *)subnode
12171217
- (void)removeFromSupernode
12181218
{
12191219
ASDisplayNodeAssertThreadAffinity(self);
1220-
ASDN::MutexLocker l(_propertyLock);
1221-
if (!_supernode)
1222-
return;
1223-
1224-
// Check to ensure that our view or layer is actually inside of our supernode; otherwise, don't remove it.
1225-
// Though _ASDisplayView decouples the supernode if it is inserted inside another view hierarchy, this is
1226-
// more difficult to guarantee with _ASDisplayLayer because CoreAnimation doesn't have a -didMoveToSuperlayer.
12271220
BOOL shouldRemoveFromSuperviewOrSuperlayer = NO;
12281221

1229-
if (self.nodeLoaded && _supernode.nodeLoaded) {
1230-
if (_flags.layerBacked || _supernode.layerBacked) {
1231-
shouldRemoveFromSuperviewOrSuperlayer = (_layer.superlayer == _supernode.layer);
1232-
} else {
1233-
shouldRemoveFromSuperviewOrSuperlayer = (_view.superview == _supernode.view);
1222+
{
1223+
ASDN::MutexLocker l(_propertyLock);
1224+
if (!_supernode)
1225+
return;
1226+
1227+
// Check to ensure that our view or layer is actually inside of our supernode; otherwise, don't remove it.
1228+
// Though _ASDisplayView decouples the supernode if it is inserted inside another view hierarchy, this is
1229+
// more difficult to guarantee with _ASDisplayLayer because CoreAnimation doesn't have a -didMoveToSuperlayer.
1230+
1231+
if (self.nodeLoaded && _supernode.nodeLoaded) {
1232+
if (_flags.layerBacked || _supernode.layerBacked) {
1233+
shouldRemoveFromSuperviewOrSuperlayer = (_layer.superlayer == _supernode.layer);
1234+
} else {
1235+
shouldRemoveFromSuperviewOrSuperlayer = (_view.superview == _supernode.view);
1236+
}
12341237
}
12351238
}
1236-
1239+
12371240
// 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.
1241+
// This call may result in the object being destroyed.
12381242
[_supernode _removeSubnode:self];
12391243

12401244
if (shouldRemoveFromSuperviewOrSuperlayer) {
12411245
ASPerformBlockOnMainThread(^{
1246+
ASDN::MutexLocker l(_propertyLock);
12421247
if (_flags.layerBacked) {
12431248
[_layer removeFromSuperlayer];
12441249
} else {
@@ -1866,7 +1871,7 @@ - (void)layout
18661871
ASDisplayNode *subnode = nil;
18671872
CGRect subnodeFrame = CGRectZero;
18681873
for (ASLayout *subnodeLayout in _layout.sublayouts) {
1869-
ASDisplayNodeAssert([_subnodes containsObject:subnodeLayout.layoutableObject], @"Cached sublayouts must only contain subnodes' layout.");
1874+
ASDisplayNodeAssert([_subnodes containsObject:subnodeLayout.layoutableObject], @"Cached sublayouts must only contain subnodes' layout. self = %@, subnodes = %@", self, _subnodes);
18701875
CGPoint adjustedOrigin = subnodeLayout.position;
18711876
if (isfinite(adjustedOrigin.x) == NO) {
18721877
ASDisplayNodeAssert(0, @"subnodeLayout has an invalid position");

0 commit comments

Comments
 (0)