mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-09 07:41:40 +00:00
Merge pull request #1605 from lappp9/override-callback-for-display-range
[ASDisplayNode] Added callbacks for entering and exiting fetch data and display ranges
This commit is contained in:
commit
a7128cd213
@ -214,9 +214,9 @@
|
||||
// To be overriden by subclasses
|
||||
}
|
||||
|
||||
- (void)visibilityDidChange:(BOOL)isVisible
|
||||
- (void)visibleStateDidChange:(BOOL)isVisible
|
||||
{
|
||||
[super visibilityDidChange:isVisible];
|
||||
[super visibleStateDidChange:isVisible];
|
||||
|
||||
CGRect cellFrame = CGRectZero;
|
||||
if (_scrollView) {
|
||||
|
||||
@ -173,9 +173,9 @@
|
||||
}
|
||||
|
||||
#if ASRangeControllerLoggingEnabled
|
||||
- (void)visibilityDidChange:(BOOL)isVisible
|
||||
- (void)visibleStateDidChange:(BOOL)isVisible
|
||||
{
|
||||
[super visibilityDidChange:isVisible];
|
||||
[super visibleStateDidChange:isVisible];
|
||||
NSLog(@"%@ - visible: %d", self, isVisible);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -242,6 +242,31 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (void)visibilityDidChange:(BOOL)isVisible ASDISPLAYNODE_REQUIRES_SUPER;
|
||||
|
||||
/**
|
||||
* @abstract Called whenever the visiblity of the node changed.
|
||||
*
|
||||
* @discussion Subclasses may use this to monitor when they become visible.
|
||||
*/
|
||||
- (void)visibleStateDidChange:(BOOL)isVisible ASDISPLAYNODE_REQUIRES_SUPER;
|
||||
|
||||
/**
|
||||
* @abstract Called whenever the the node has entered or exited the display state.
|
||||
*
|
||||
* @discussion Subclasses may use this to monitor when a node should be rendering its content.
|
||||
*
|
||||
* @note This method can be called from any thread and should therefore be thread safe.
|
||||
*/
|
||||
- (void)displayStateDidChange:(BOOL)inDisplayState ASDISPLAYNODE_REQUIRES_SUPER;
|
||||
|
||||
/**
|
||||
* @abstract Called whenever the the node has entered or left the load state.
|
||||
*
|
||||
* @discussion Subclasses may use this to monitor data for a node should be loaded, either from a local or remote source.
|
||||
*
|
||||
* @note This method can be called from any thread and should therefore be thread safe.
|
||||
*/
|
||||
- (void)loadStateDidChange:(BOOL)inLoadState ASDISPLAYNODE_REQUIRES_SUPER;
|
||||
|
||||
/**
|
||||
* Called just before the view is added to a window.
|
||||
*/
|
||||
|
||||
@ -2044,6 +2044,8 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
ASDisplayNodeAssertMainThread();
|
||||
}
|
||||
|
||||
#pragma mark Hierarchy State
|
||||
|
||||
- (void)willEnterHierarchy
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
@ -2064,7 +2066,7 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
if (![self supportsRangeManagedInterfaceState]) {
|
||||
self.interfaceState = ASInterfaceStateNone;
|
||||
} else {
|
||||
// This case is important when tearing down hierarchies. We must deliver a visibilityDidChange:NO callback, as part our API guarantee that this method can be used for
|
||||
// This case is important when tearing down hierarchies. We must deliver a visibileStateDidChange:NO callback, as part our API guarantee that this method can be used for
|
||||
// things like data analytics about user content viewing. We cannot call the method in the dealloc as any incidental retain operations in client code would fail.
|
||||
// Additionally, it may be that a Standard UIView which is containing us is moving between hierarchies, and we should not send the call if we will be re-added in the
|
||||
// same runloop. Strategy: strong reference (might be the last!), wait one runloop, and confirm we are still outside the hierarchy (both layer-backed and view-backed).
|
||||
@ -2083,6 +2085,8 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark Interface State
|
||||
|
||||
- (void)clearContents
|
||||
{
|
||||
// No-op if these haven't been created yet, as that guarantees they don't have contents that needs to be released.
|
||||
@ -2131,7 +2135,22 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
|
||||
- (void)visibilityDidChange:(BOOL)isVisible
|
||||
{
|
||||
// subclass override
|
||||
// subclass override
|
||||
}
|
||||
|
||||
- (void)visibleStateDidChange:(BOOL)isVisible
|
||||
{
|
||||
// subclass override
|
||||
}
|
||||
|
||||
- (void)displayStateDidChange:(BOOL)inDisplayState
|
||||
{
|
||||
//subclass override
|
||||
}
|
||||
|
||||
- (void)loadStateDidChange:(BOOL)inLoadState
|
||||
{
|
||||
//subclass override
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2178,10 +2197,12 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
if (nowFetchData != wasFetchData) {
|
||||
if (nowFetchData) {
|
||||
[self fetchData];
|
||||
[self loadStateDidChange:YES];
|
||||
} else {
|
||||
if ([self supportsRangeManagedInterfaceState]) {
|
||||
[self clearFetchedData];
|
||||
}
|
||||
[self loadStateDidChange:NO];
|
||||
}
|
||||
}
|
||||
|
||||
@ -2225,6 +2246,8 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[self displayStateDidChange:nowDisplay];
|
||||
}
|
||||
|
||||
// Became visible or invisible. When range-managed, this represents literal visibility - at least one pixel
|
||||
@ -2233,14 +2256,16 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
|
||||
BOOL wasVisible = ASInterfaceStateIncludesVisible(oldState);
|
||||
|
||||
if (nowVisible != wasVisible) {
|
||||
[self visibilityDidChange:nowVisible];
|
||||
[self visibleStateDidChange:nowVisible];
|
||||
[self visibilityDidChange:nowVisible]; //TODO: remove once this method has been deprecated
|
||||
}
|
||||
|
||||
|
||||
[self interfaceStateDidChange:newState fromState:oldState];
|
||||
}
|
||||
|
||||
- (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfaceState)oldState
|
||||
{
|
||||
// subclass hook
|
||||
}
|
||||
|
||||
- (void)enterInterfaceState:(ASInterfaceState)interfaceState
|
||||
|
||||
@ -158,9 +158,9 @@ NSString *const ASAnimatedImageDefaultRunLoopMode = NSDefaultRunLoopMode;
|
||||
[self.animatedImage clearAnimatedImageCache];
|
||||
}
|
||||
|
||||
- (void)visibilityDidChange:(BOOL)isVisible
|
||||
- (void)visibleStateDidChange:(BOOL)isVisible
|
||||
{
|
||||
[super visibilityDidChange:isVisible];
|
||||
[super visibleStateDidChange:isVisible];
|
||||
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (isVisible) {
|
||||
|
||||
@ -295,11 +295,11 @@ typedef void(^ASMultiplexImageLoadCompletionBlock)(UIImage *image, id imageIdent
|
||||
}
|
||||
}
|
||||
|
||||
/* visibilityDidChange in ASNetworkImageNode has a very similar implementation. Changes here are likely necessary
|
||||
/* visibileStateDidChange in ASNetworkImageNode has a very similar implementation. Changes here are likely necessary
|
||||
in ASNetworkImageNode as well. */
|
||||
- (void)visibilityDidChange:(BOOL)isVisible
|
||||
- (void)visibleStateDidChange:(BOOL)isVisible
|
||||
{
|
||||
[super visibilityDidChange:isVisible];
|
||||
[super visibleStateDidChange:isVisible];
|
||||
|
||||
if (_downloaderImplementsSetPriority) {
|
||||
ASDN::MutexLocker l(_downloadIdentifierLock);
|
||||
|
||||
@ -278,11 +278,11 @@ static const CGSize kMinReleaseImageOnBackgroundSize = {20.0, 20.0};
|
||||
}
|
||||
}
|
||||
|
||||
/* visibilityDidChange in ASMultiplexImageNode has a very similar implementation. Changes here are likely necessary
|
||||
/* visibileStateDidChange in ASMultiplexImageNode has a very similar implementation. Changes here are likely necessary
|
||||
in ASMultiplexImageNode as well. */
|
||||
- (void)visibilityDidChange:(BOOL)isVisible
|
||||
- (void)visibleStateDidChange:(BOOL)isVisible
|
||||
{
|
||||
[super visibilityDidChange:isVisible];
|
||||
[super visibleStateDidChange:isVisible];
|
||||
|
||||
if (_downloaderImplementsSetPriority) {
|
||||
_lock.lock();
|
||||
|
||||
@ -145,9 +145,9 @@
|
||||
}
|
||||
|
||||
#if ASRangeControllerLoggingEnabled
|
||||
- (void)visibilityDidChange:(BOOL)isVisible
|
||||
- (void)visibleStateDidChange:(BOOL)isVisible
|
||||
{
|
||||
[super visibilityDidChange:isVisible];
|
||||
[super visibleStateDidChange:isVisible];
|
||||
NSLog(@"%@ - visible: %d", self, isVisible);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -382,9 +382,9 @@ static NSString * const kStatus = @"status";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)visibilityDidChange:(BOOL)isVisible
|
||||
- (void)visibleStateDidChange:(BOOL)isVisible
|
||||
{
|
||||
[super visibilityDidChange:isVisible];
|
||||
[super visibleStateDidChange:isVisible];
|
||||
|
||||
ASDN::MutexLocker l(_videoLock);
|
||||
|
||||
|
||||
@ -163,9 +163,9 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)visibilityDidChange:(BOOL)isVisible
|
||||
- (void)visibleStateDidChange:(BOOL)isVisible
|
||||
{
|
||||
[super visibilityDidChange:isVisible];
|
||||
[super visibleStateDidChange:isVisible];
|
||||
|
||||
ASDN::MutexLocker l(_videoPlayerLock);
|
||||
|
||||
|
||||
@ -95,7 +95,7 @@ static UIApplicationState __ApplicationState = UIApplicationStateActive;
|
||||
{
|
||||
_scrollDirection = scrollDirection;
|
||||
|
||||
// Perform update immediately, so that cells receive a visibilityDidChange: call before their first pixel is visible.
|
||||
// Perform update immediately, so that cells receive a visibleStateDidChange: call before their first pixel is visible.
|
||||
[self scheduleRangeUpdate];
|
||||
}
|
||||
|
||||
|
||||
@ -86,6 +86,12 @@ for (ASDisplayNode *n in @[ nodes ]) {\
|
||||
@property (atomic, copy) void (^willDeallocBlock)(ASTestDisplayNode *node);
|
||||
@property (atomic, copy) CGSize(^calculateSizeBlock)(ASTestDisplayNode *node, CGSize size);
|
||||
@property (atomic) BOOL hasFetchedData;
|
||||
|
||||
@property (atomic) BOOL displayRangeStateChangedToYES;
|
||||
@property (atomic) BOOL displayRangeStateChangedToNO;
|
||||
|
||||
@property (atomic) BOOL loadStateChangedToYES;
|
||||
@property (atomic) BOOL loadStateChangedToNO;
|
||||
@end
|
||||
|
||||
@interface ASTestResponderNode : ASTestDisplayNode
|
||||
@ -110,6 +116,28 @@ for (ASDisplayNode *n in @[ nodes ]) {\
|
||||
self.hasFetchedData = NO;
|
||||
}
|
||||
|
||||
- (void)displayStateDidChange:(BOOL)inDisplayState
|
||||
{
|
||||
[super displayStateDidChange:inDisplayState];
|
||||
|
||||
if (inDisplayState) {
|
||||
self.displayRangeStateChangedToYES = YES;
|
||||
} else {
|
||||
self.displayRangeStateChangedToNO = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)loadStateDidChange:(BOOL)inLoadState
|
||||
{
|
||||
[super loadStateDidChange:inLoadState];
|
||||
|
||||
if (inLoadState) {
|
||||
self.loadStateChangedToYES = YES;
|
||||
} else {
|
||||
self.loadStateChangedToNO = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
if (_willDeallocBlock) {
|
||||
@ -1878,4 +1906,42 @@ static bool stringContainsPointer(NSString *description, const void *p) {
|
||||
XCTAssert(node.bounds.size.height == 8, @"Wrong ASDisplayNode.bounds.size.height");
|
||||
}
|
||||
|
||||
- (void)testDidEnterDisplayIsCalledWhenNodesEnterDisplayRange
|
||||
{
|
||||
ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init];
|
||||
|
||||
[node recursivelySetInterfaceState:ASInterfaceStateDisplay];
|
||||
|
||||
XCTAssert([node displayRangeStateChangedToYES]);
|
||||
}
|
||||
|
||||
- (void)testDidExitDisplayIsCalledWhenNodesExitDisplayRange
|
||||
{
|
||||
ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init];
|
||||
|
||||
[node recursivelySetInterfaceState:ASInterfaceStateDisplay];
|
||||
[node recursivelySetInterfaceState:ASInterfaceStateFetchData];
|
||||
|
||||
XCTAssert([node displayRangeStateChangedToNO]);
|
||||
}
|
||||
|
||||
- (void)testDidEnterFetchDataIsCalledWhenNodesEnterFetchDataRange
|
||||
{
|
||||
ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init];
|
||||
|
||||
[node recursivelySetInterfaceState:ASInterfaceStateFetchData];
|
||||
|
||||
XCTAssert([node loadStateChangedToYES]);
|
||||
}
|
||||
|
||||
- (void)testDidExitFetchDataIsCalledWhenNodesExitFetchDataRange
|
||||
{
|
||||
ASTestDisplayNode *node = [[ASTestDisplayNode alloc] init];
|
||||
|
||||
[node recursivelySetInterfaceState:ASInterfaceStateFetchData];
|
||||
[node recursivelySetInterfaceState:ASInterfaceStateDisplay];
|
||||
|
||||
XCTAssert([node loadStateChangedToNO]);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -223,12 +223,11 @@
|
||||
}];
|
||||
_videoNode.playerNode.layer.frame = CGRectZero;
|
||||
|
||||
[_videoNode visibilityDidChange:YES];
|
||||
[_videoNode visibleStateDidChange:YES];
|
||||
|
||||
XCTAssertTrue(_videoNode.shouldBePlaying);
|
||||
}
|
||||
|
||||
|
||||
- (void)testVideoShouldPauseWhenItLeavesVisibleButShouldKnowPlayingShouldRestartLater
|
||||
{
|
||||
_videoNode.asset = _firstAsset;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user