mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Make sure range controller listens to node display notifications if absolutely needed
This commit is contained in:
@@ -245,9 +245,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
|||||||
dispatch_once(&onceToken, ^{
|
dispatch_once(&onceToken, ^{
|
||||||
renderQueue = [[ASRunLoopQueue<ASDisplayNode *> alloc] initWithRunLoop:CFRunLoopGetMain()
|
renderQueue = [[ASRunLoopQueue<ASDisplayNode *> alloc] initWithRunLoop:CFRunLoopGetMain()
|
||||||
andHandler:^(ASDisplayNode * _Nonnull dequeuedItem, BOOL isQueueDrained) {
|
andHandler:^(ASDisplayNode * _Nonnull dequeuedItem, BOOL isQueueDrained) {
|
||||||
CFAbsoluteTime timestamp = isQueueDrained ? CFAbsoluteTimeGetCurrent() : 0;
|
|
||||||
[dequeuedItem _recursivelyTriggerDisplayAndBlock:NO];
|
[dequeuedItem _recursivelyTriggerDisplayAndBlock:NO];
|
||||||
if (isQueueDrained) {
|
if (isQueueDrained) {
|
||||||
|
CFAbsoluteTime timestamp = CFAbsoluteTimeGetCurrent();
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:ASRenderingEngineDidDisplayScheduledNodesNotification
|
[[NSNotificationCenter defaultCenter] postNotificationName:ASRenderingEngineDidDisplayScheduledNodesNotification
|
||||||
object:nil
|
object:nil
|
||||||
userInfo:@{ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp: @(timestamp)}];
|
userInfo:@{ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp: @(timestamp)}];
|
||||||
@@ -2317,25 +2317,25 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)recursivelySetInterfaceState:(ASInterfaceState)interfaceState
|
- (void)recursivelySetInterfaceState:(ASInterfaceState)newInterfaceState
|
||||||
{
|
{
|
||||||
ASInterfaceState oldState = self.interfaceState;
|
|
||||||
ASInterfaceState newState = interfaceState;
|
|
||||||
ASDisplayNodePerformBlockOnEveryNode(nil, self, ^(ASDisplayNode *node) {
|
|
||||||
node.interfaceState = interfaceState;
|
|
||||||
});
|
|
||||||
|
|
||||||
if ([self supportsRangeManagedInterfaceState]) {
|
|
||||||
// Instead of each node in the recursion assuming it needs to schedule itself for display,
|
// Instead of each node in the recursion assuming it needs to schedule itself for display,
|
||||||
// setInterfaceState: skips this when handling range-managed nodes (our whole subtree has this set).
|
// setInterfaceState: skips this when handling range-managed nodes (our whole subtree has this set).
|
||||||
// If our range manager intends for us to be displayed right now, and didn't before, get started!
|
// If our range manager intends for us to be displayed right now, and didn't before, get started!
|
||||||
|
BOOL shouldScheduleDisplay = [self supportsRangeManagedInterfaceState] && [self shouldScheduleDisplayWithNewInterfaceState:newInterfaceState];
|
||||||
BOOL nowDisplay = ASInterfaceStateIncludesDisplay(newState);
|
ASDisplayNodePerformBlockOnEveryNode(nil, self, ^(ASDisplayNode *node) {
|
||||||
BOOL wasDisplay = ASInterfaceStateIncludesDisplay(oldState);
|
node.interfaceState = newInterfaceState;
|
||||||
if (nowDisplay && (nowDisplay != wasDisplay)) {
|
});
|
||||||
|
if (shouldScheduleDisplay) {
|
||||||
[ASDisplayNode scheduleNodeForRecursiveDisplay:self];
|
[ASDisplayNode scheduleNodeForRecursiveDisplay:self];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)shouldScheduleDisplayWithNewInterfaceState:(ASInterfaceState)newInterfaceState
|
||||||
|
{
|
||||||
|
BOOL willDisplay = ASInterfaceStateIncludesDisplay(newInterfaceState);
|
||||||
|
BOOL nowDisplay = ASInterfaceStateIncludesDisplay(self.interfaceState);
|
||||||
|
return willDisplay && (willDisplay != nowDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASHierarchyState)hierarchyState
|
- (ASHierarchyState)hierarchyState
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
NSSet<NSIndexPath *> *_allPreviousIndexPaths;
|
NSSet<NSIndexPath *> *_allPreviousIndexPaths;
|
||||||
ASLayoutRangeMode _currentRangeMode;
|
ASLayoutRangeMode _currentRangeMode;
|
||||||
BOOL _didUpdateCurrentRange;
|
BOOL _didUpdateCurrentRange;
|
||||||
BOOL _didRegisterForNotifications;
|
BOOL _didRegisterForNodeDisplayNotifications;
|
||||||
CFAbsoluteTime _pendingDisplayNodesTimestamp;
|
CFAbsoluteTime _pendingDisplayNodesTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
|
|||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
if (_didRegisterForNotifications) {
|
if (_didRegisterForNodeDisplayNotifications) {
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:ASRenderingEngineDidDisplayScheduledNodesNotification object:nil];
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:ASRenderingEngineDidDisplayScheduledNodesNotification object:nil];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,10 +242,6 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
|
|||||||
[allIndexPaths addObjectsFromArray:ASIndexPathsForTwoDimensionalArray(allNodes)];
|
[allIndexPaths addObjectsFromArray:ASIndexPathsForTwoDimensionalArray(allNodes)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Don't register for notifications if this range update doesn't cause any node to enter rendering pipeline.
|
|
||||||
// This can be done once there is an API to observe to (or be notified upon) interface state changes or pipeline enterings
|
|
||||||
[self registerForNotificationsForInterfaceStateIfNeeded:selfInterfaceState];
|
|
||||||
|
|
||||||
#if ASRangeControllerLoggingEnabled
|
#if ASRangeControllerLoggingEnabled
|
||||||
ASDisplayNodeAssertTrue([visibleIndexPaths isSubsetOfSet:displayIndexPaths]);
|
ASDisplayNodeAssertTrue([visibleIndexPaths isSubsetOfSet:displayIndexPaths]);
|
||||||
NSMutableArray<NSIndexPath *> *modifiedIndexPaths = (ASRangeControllerLoggingEnabled ? [NSMutableArray array] : nil);
|
NSMutableArray<NSIndexPath *> *modifiedIndexPaths = (ASRangeControllerLoggingEnabled ? [NSMutableArray array] : nil);
|
||||||
@@ -309,15 +305,20 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
|
|||||||
#if ASRangeControllerLoggingEnabled
|
#if ASRangeControllerLoggingEnabled
|
||||||
[modifiedIndexPaths addObject:indexPath];
|
[modifiedIndexPaths addObject:indexPath];
|
||||||
#endif
|
#endif
|
||||||
[node recursivelySetInterfaceState:interfaceState];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_didRegisterForNotifications) {
|
BOOL nodeShouldScheduleDisplay = [node shouldScheduleDisplayWithNewInterfaceState:interfaceState];
|
||||||
|
[node recursivelySetInterfaceState:interfaceState];
|
||||||
|
|
||||||
|
if (nodeShouldScheduleDisplay) {
|
||||||
|
[self registerForNodeDisplayNotificationsForInterfaceStateIfNeeded:selfInterfaceState];
|
||||||
|
if (_didRegisterForNodeDisplayNotifications) {
|
||||||
_pendingDisplayNodesTimestamp = CFAbsoluteTimeGetCurrent();
|
_pendingDisplayNodesTimestamp = CFAbsoluteTimeGetCurrent();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_rangeIsValid = YES;
|
_rangeIsValid = YES;
|
||||||
_queuedRangeUpdate = NO;
|
_queuedRangeUpdate = NO;
|
||||||
@@ -338,9 +339,9 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
|
|||||||
|
|
||||||
#pragma mark - Notification observers
|
#pragma mark - Notification observers
|
||||||
|
|
||||||
- (void)registerForNotificationsForInterfaceStateIfNeeded:(ASInterfaceState)interfaceState
|
- (void)registerForNodeDisplayNotificationsForInterfaceStateIfNeeded:(ASInterfaceState)interfaceState
|
||||||
{
|
{
|
||||||
if (!_didRegisterForNotifications) {
|
if (!_didRegisterForNodeDisplayNotifications) {
|
||||||
ASLayoutRangeMode nextRangeMode = [ASRangeController rangeModeForInterfaceState:interfaceState
|
ASLayoutRangeMode nextRangeMode = [ASRangeController rangeModeForInterfaceState:interfaceState
|
||||||
currentRangeMode:_currentRangeMode];
|
currentRangeMode:_currentRangeMode];
|
||||||
if (_currentRangeMode != nextRangeMode) {
|
if (_currentRangeMode != nextRangeMode) {
|
||||||
@@ -348,7 +349,7 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
|
|||||||
selector:@selector(scheduledNodesDidDisplay:)
|
selector:@selector(scheduledNodesDidDisplay:)
|
||||||
name:ASRenderingEngineDidDisplayScheduledNodesNotification
|
name:ASRenderingEngineDidDisplayScheduledNodesNotification
|
||||||
object:nil];
|
object:nil];
|
||||||
_didRegisterForNotifications = YES;
|
_didRegisterForNodeDisplayNotifications = YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,7 +360,7 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
|
|||||||
if (_pendingDisplayNodesTimestamp < notificationTimestamp) {
|
if (_pendingDisplayNodesTimestamp < notificationTimestamp) {
|
||||||
// The rendering engine has processed all the nodes this range controller scheduled. Let's schedule a range update
|
// The rendering engine has processed all the nodes this range controller scheduled. Let's schedule a range update
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:ASRenderingEngineDidDisplayScheduledNodesNotification object:nil];
|
[[NSNotificationCenter defaultCenter] removeObserver:self name:ASRenderingEngineDidDisplayScheduledNodesNotification object:nil];
|
||||||
_didRegisterForNotifications = NO;
|
_didRegisterForNodeDisplayNotifications = NO;
|
||||||
|
|
||||||
[self scheduleRangeUpdate];
|
[self scheduleRangeUpdate];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,6 +135,11 @@ inline BOOL ASHierarchyStateIncludesRangeManaged(ASHierarchyState hierarchyState
|
|||||||
*/
|
*/
|
||||||
@property (nonatomic, assign) BOOL shouldBypassEnsureDisplay;
|
@property (nonatomic, assign) BOOL shouldBypassEnsureDisplay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Checks whether a node should be scheduled for display, considering its current and new interface states.
|
||||||
|
*/
|
||||||
|
- (BOOL)shouldScheduleDisplayWithNewInterfaceState:(ASInterfaceState)newInterfaceState;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface UIView (ASDisplayNodeInternal)
|
@interface UIView (ASDisplayNodeInternal)
|
||||||
|
|||||||
Reference in New Issue
Block a user