mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-23 14:05:33 +00:00
This brings back the concept of a window store for nodes that are in the working range (reverting #127). It turns out that due to the system architecture if there are nodes who fetch remote content (e.g. `ASNetworkImageNode`), calls to `-display` will occur before fetching has been completed. The next chance the nodes have to decode and display content is then when they are actually on the screen, thus defeating the purpose of a working range. With the reintroduction of the working range window, nodes are "stored" in the window and when content is finished being fetched, CA triggers `-display` since they are part of a view hierarchy. This can be tested in the Kittens project by insuring that before `ASRangeController` adds a node to [a visible view](https://github.com/facebook/AsyncDisplayKit/blob/master/AsyncDisplayKit/Details/ASRangeController.mm#L57) that the image node (with remote content) has set its layer's contents.
57 lines
1.7 KiB
Plaintext
57 lines
1.7 KiB
Plaintext
/* Copyright (c) 2014-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
|
|
#import "ASRangeHandlerRender.h"
|
|
|
|
#import "ASDisplayNode.h"
|
|
#import "ASDisplayNode+Subclasses.h"
|
|
#import "ASDisplayNodeInternal.h"
|
|
|
|
@implementation ASRangeHandlerRender
|
|
|
|
+ (UIWindow *)workingWindow
|
|
{
|
|
ASDisplayNodeAssertMainThread();
|
|
|
|
// we add nodes' views to this invisible window to start async rendering
|
|
static UIWindow *workingWindow = nil;
|
|
static dispatch_once_t onceToken;
|
|
dispatch_once(&onceToken, ^{
|
|
workingWindow = [[UIWindow alloc] initWithFrame:CGRectZero];
|
|
workingWindow.windowLevel = UIWindowLevelNormal - 1000;
|
|
workingWindow.userInteractionEnabled = NO;
|
|
workingWindow.clipsToBounds = YES;
|
|
workingWindow.hidden = YES;
|
|
});
|
|
return workingWindow;
|
|
}
|
|
|
|
- (void)node:(ASDisplayNode *)node enteredRangeOfType:(ASLayoutRangeType)rangeType
|
|
{
|
|
ASDisplayNodeAssertMainThread();
|
|
ASDisplayNodeAssert(rangeType == ASLayoutRangeTypeRender, @"Render delegate should not handle other ranges");
|
|
|
|
[node recursivelySetDisplaySuspended:NO];
|
|
|
|
// add the node to an off-screen window to force display and preserve its contents
|
|
[[self.class workingWindow] addSubnode:node];
|
|
}
|
|
|
|
- (void)node:(ASDisplayNode *)node exitedRangeOfType:(ASLayoutRangeType)rangeType
|
|
{
|
|
ASDisplayNodeAssertMainThread();
|
|
ASDisplayNodeAssert(rangeType == ASLayoutRangeTypeRender, @"Render delegate should not handle other ranges");
|
|
|
|
[node recursivelySetDisplaySuspended:YES];
|
|
[node.view removeFromSuperview];
|
|
|
|
[node recursivelyClearRendering];
|
|
}
|
|
|
|
@end
|