mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
Initial commit to throw an exception if manually adding / removing subnodes if node has automaticallyManagesSubnodes enabled (#2214)
This commit is contained in:
committed by
Adlai Holler
parent
53a6743908
commit
0d8518912e
@@ -1553,6 +1553,12 @@ static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASD
|
||||
}
|
||||
|
||||
- (void)addSubnode:(ASDisplayNode *)subnode
|
||||
{
|
||||
ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually add subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode);
|
||||
[self _addSubnode:subnode];
|
||||
}
|
||||
|
||||
- (void)_addSubnode:(ASDisplayNode *)subnode
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
@@ -1568,7 +1574,7 @@ static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASD
|
||||
if (isMovingEquivalentParents) {
|
||||
[subnode __incrementVisibilityNotificationsDisabled];
|
||||
}
|
||||
[subnode removeFromSupernode];
|
||||
[subnode _removeFromSupernode];
|
||||
|
||||
if (!_subnodes) {
|
||||
_subnodes = [[NSMutableArray alloc] init];
|
||||
@@ -1624,8 +1630,8 @@ static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASD
|
||||
[subnode __incrementVisibilityNotificationsDisabled];
|
||||
}
|
||||
|
||||
[subnode removeFromSupernode];
|
||||
[oldSubnode removeFromSupernode];
|
||||
[subnode _removeFromSupernode];
|
||||
[oldSubnode _removeFromSupernode];
|
||||
|
||||
if (!_subnodes)
|
||||
_subnodes = [[NSMutableArray alloc] init];
|
||||
@@ -1661,6 +1667,12 @@ static bool disableNotificationsForMovingBetweenParents(ASDisplayNode *from, ASD
|
||||
}
|
||||
|
||||
- (void)replaceSubnode:(ASDisplayNode *)oldSubnode withSubnode:(ASDisplayNode *)replacementSubnode
|
||||
{
|
||||
ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually replace old node with replacement node to node with automaticallyManagesSubnodes=YES. Old Node: %@, replacement node: %@", oldSubnode, replacementSubnode);
|
||||
[self _replaceSubnode:oldSubnode withSubnode:replacementSubnode];
|
||||
}
|
||||
|
||||
- (void)_replaceSubnode:(ASDisplayNode *)oldSubnode withSubnode:(ASDisplayNode *)replacementSubnode
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
@@ -1691,6 +1703,12 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
}
|
||||
|
||||
- (void)insertSubnode:(ASDisplayNode *)subnode belowSubnode:(ASDisplayNode *)below
|
||||
{
|
||||
ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually insert subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode);
|
||||
[self _insertSubnode:subnode belowSubnode:below];
|
||||
}
|
||||
|
||||
- (void)_insertSubnode:(ASDisplayNode *)subnode belowSubnode:(ASDisplayNode *)below
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
@@ -1736,6 +1754,12 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
}
|
||||
|
||||
- (void)insertSubnode:(ASDisplayNode *)subnode aboveSubnode:(ASDisplayNode *)above
|
||||
{
|
||||
ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually insert subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode);
|
||||
[self _insertSubnode:subnode aboveSubnode:above];
|
||||
}
|
||||
|
||||
- (void)_insertSubnode:(ASDisplayNode *)subnode aboveSubnode:(ASDisplayNode *)above
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
@@ -1784,6 +1808,12 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
}
|
||||
|
||||
- (void)insertSubnode:(ASDisplayNode *)subnode atIndex:(NSInteger)idx
|
||||
{
|
||||
ASDisplayNodeAssert(self.automaticallyManagesSubnodes == NO, @"Attempt to manually insert subnode to node with automaticallyManagesSubnodes=YES. Node: %@", subnode);
|
||||
[self _insertSubnode:subnode atIndex:idx];
|
||||
}
|
||||
|
||||
- (void)_insertSubnode:(ASDisplayNode *)subnode atIndex:(NSInteger)idx
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
@@ -1854,10 +1884,18 @@ static NSInteger incrementIfFound(NSInteger i) {
|
||||
[subnode __setSupernode:nil];
|
||||
}
|
||||
|
||||
// NOTE: You must not called this method while holding the receiver's property lock. This may cause deadlocks.
|
||||
- (void)removeFromSupernode
|
||||
{
|
||||
ASDisplayNodeAssert(self.supernode.automaticallyManagesSubnodes == NO, @"Attempt to manually remove subnode from node with automaticallyManagesSubnodes=YES. Node: %@", self);
|
||||
|
||||
[self _removeFromSupernode];
|
||||
}
|
||||
|
||||
// NOTE: You must not called this method while holding the receiver's property lock. This may cause deadlocks.
|
||||
- (void)_removeFromSupernode
|
||||
{
|
||||
ASDisplayNodeAssertThreadAffinity(self);
|
||||
|
||||
__instanceLock__.lock();
|
||||
__weak ASDisplayNode *supernode = _supernode;
|
||||
__weak UIView *view = _view;
|
||||
|
||||
@@ -199,6 +199,17 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
|
||||
- (void)__layout;
|
||||
- (void)__setSupernode:(ASDisplayNode *)supernode;
|
||||
|
||||
/**
|
||||
Internal method to add / replace / insert subnode and remove from supernode without checking if
|
||||
node has automaticallyManagesSubnodes set to YES.
|
||||
*/
|
||||
- (void)_addSubnode:(ASDisplayNode *)subnode;
|
||||
- (void)_replaceSubnode:(ASDisplayNode *)oldSubnode withSubnode:(ASDisplayNode *)replacementSubnode;
|
||||
- (void)_insertSubnode:(ASDisplayNode *)subnode belowSubnode:(ASDisplayNode *)below;
|
||||
- (void)_insertSubnode:(ASDisplayNode *)subnode aboveSubnode:(ASDisplayNode *)above;
|
||||
- (void)_insertSubnode:(ASDisplayNode *)subnode atIndex:(NSInteger)idx;
|
||||
- (void)_removeFromSupernode;
|
||||
|
||||
// Private API for helper functions / unit tests. Use ASDisplayNodeDisableHierarchyNotifications() to control this.
|
||||
- (BOOL)__visibilityNotificationsDisabled;
|
||||
- (BOOL)__selfOrParentHasVisibilityNotificationsDisabled;
|
||||
|
||||
@@ -98,7 +98,7 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) {
|
||||
NSUInteger i = 0;
|
||||
for (ASDisplayNode *node in _insertedSubnodes) {
|
||||
NSUInteger p = _insertedSubnodePositions[i];
|
||||
[_node insertSubnode:node atIndex:p];
|
||||
[_node _insertSubnode:node atIndex:p];
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) {
|
||||
ASDN::MutexSharedLocker l(__instanceLock__);
|
||||
[self calculateSubnodeOperationsIfNeeded];
|
||||
for (ASDisplayNode *subnode in _removedSubnodes) {
|
||||
[subnode removeFromSupernode];
|
||||
[subnode _removeFromSupernode];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#import "ASStaticLayoutSpec.h"
|
||||
#import "ASStackLayoutSpec.h"
|
||||
#import "ASInsetLayoutSpec.h"
|
||||
|
||||
@interface ASSpecTestDisplayNode : ASDisplayNode
|
||||
|
||||
@@ -117,9 +118,24 @@
|
||||
XCTAssertEqual(node.subnodes[2], node2);
|
||||
}
|
||||
|
||||
- (void)testLayoutTransitionWillThrowForManualSubnodeManagement
|
||||
{
|
||||
ASDisplayNode *node1 = [[ASDisplayNode alloc] init];
|
||||
node1.name = @"node1";
|
||||
|
||||
ASSpecTestDisplayNode *node = [[ASSpecTestDisplayNode alloc] init];
|
||||
node.automaticallyManagesSubnodes = YES;
|
||||
node.layoutSpecBlock = ^ASLayoutSpec *(ASDisplayNode *weakNode, ASSizeRange constrainedSize){
|
||||
return [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[node1]];
|
||||
};
|
||||
|
||||
XCTAssertNoThrow([node layoutThatFits:ASSizeRangeMake(CGSizeZero)]);
|
||||
XCTAssertThrows([node1 removeFromSupernode]);
|
||||
}
|
||||
|
||||
- (void)testLayoutTransitionMeasurementCompletionBlockIsCalledOnMainThread
|
||||
{
|
||||
ASDisplayNode *displayNode = [ASDisplayNode new];
|
||||
ASDisplayNode *displayNode = [[ASDisplayNode alloc] init];
|
||||
|
||||
// Trigger explicit view creation to be able to use the Transition API
|
||||
[displayNode view];
|
||||
|
||||
Reference in New Issue
Block a user