mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-11 08:50:24 +00:00
[ASDisplayNode+Layout] Add check for orphaned nodes after layout transition to clean up. (#336)
It is rare that this code has any effect, but I've discovered a case in which it occurs. This task tracks moving this code to a DEBUG-only assertion: https://github.com/TextureGroup/Texture/issues/335
This commit is contained in:
parent
a9837f2dc8
commit
00013aadab
@ -1,6 +1,7 @@
|
||||
## master
|
||||
|
||||
* Add your own contributions to the next release on the line below this with your name.
|
||||
- [ASDisplayNode+Layout] Add check for orphaned nodes after layout transition to clean up. #336. [Scott Goodson](https://github.com/appleguy)
|
||||
- Fixed an issue where GIFs with placeholders never had their placeholders uncover the GIF. [Garrett Moon](https://github.com/garrettmoon)
|
||||
- [Yoga] Implement ASYogaLayoutSpec, a simplified integration strategy for Yoga-powered layout calculation. [Scott Goodson](https://github.com/appleguy)
|
||||
- Fixed an issue where calls to setNeedsDisplay and setNeedsLayout would stop working on loaded nodes. [Garrett Moon](https://github.com/garrettmoon)
|
||||
|
||||
@ -817,11 +817,54 @@ ASPrimitiveTraitCollectionDeprecatedImplementation
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_assertSubnodeState
|
||||
{
|
||||
// Verify that any orphaned nodes are removed.
|
||||
// This can occur in rare cases if main thread layout is flushed while a background layout is calculating.
|
||||
|
||||
if (self.automaticallyManagesSubnodes == NO) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSArray *subnodes = [self subnodes];
|
||||
NSArray *sublayouts = _calculatedDisplayNodeLayout->layout.sublayouts;
|
||||
|
||||
auto currentSubnodes = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality
|
||||
capacity:subnodes.count];
|
||||
auto layoutSubnodes = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality
|
||||
capacity:sublayouts.count];;
|
||||
for (ASDisplayNode *subnode in subnodes) {
|
||||
[currentSubnodes addObject:subnode];
|
||||
}
|
||||
|
||||
for (ASLayout *sublayout in sublayouts) {
|
||||
id <ASLayoutElement> layoutElement = sublayout.layoutElement;
|
||||
ASDisplayNodeAssert([layoutElement isKindOfClass:[ASDisplayNode class]],
|
||||
@"All calculatedLayouts should be flattened and only contain nodes!");
|
||||
[layoutSubnodes addObject:(ASDisplayNode *)layoutElement];
|
||||
}
|
||||
|
||||
// Verify that all subnodes that occur in the current ASLayout tree are present in .subnodes array.
|
||||
if ([layoutSubnodes isSubsetOfHashTable:currentSubnodes] == NO) {
|
||||
// Note: This should be converted to an assertion after confirming it is rare.
|
||||
NSLog(@"Warning: node's layout includes subnodes that have not been added: node = %@, subnodes = %@, subnodes in layout = %@", self, currentSubnodes, layoutSubnodes);
|
||||
}
|
||||
|
||||
// Verify that everything in the .subnodes array is present in the ASLayout tree (and correct it if not).
|
||||
[currentSubnodes minusHashTable:layoutSubnodes];
|
||||
for (ASDisplayNode *orphanedSubnode in currentSubnodes) {
|
||||
NSLog(@"Automatically removing orphaned subnode %@, from parent %@", orphanedSubnode, self);
|
||||
[orphanedSubnode removeFromSupernode];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_pendingLayoutTransitionDidComplete
|
||||
{
|
||||
[self _assertSubnodeState];
|
||||
|
||||
// Subclass hook
|
||||
[self calculatedLayoutDidChange];
|
||||
|
||||
|
||||
// Grab lock after calling out to subclass
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user