mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-17 03:40:18 +00:00
Adds support for having multiple interface state delegates. (#979)
* Adds support for having multiple interface state delegates. Hopefully in a performant way. * Switch to respondsToSelector for int del instead of separate object * Add CHANGELOG * Make ASDisplayNode+InterfaceState.h public * Huy's comments * Don't even bother removing since it's a weak hash table.
This commit is contained in:
parent
f0dac14505
commit
a4f78ad3e0
@ -115,6 +115,7 @@
|
|||||||
68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */; };
|
68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */; };
|
||||||
68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */; };
|
68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */; };
|
||||||
68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
|
683F563720E409D700CEB7A3 /* ASDisplayNode+InterfaceState.h in Headers */ = {isa = PBXBuildFile; fileRef = 683F563620E409D600CEB7A3 /* ASDisplayNode+InterfaceState.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
68AF37DB1CBEF4D80077BF76 /* ASImageNode+AnimatedImagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
68AF37DB1CBEF4D80077BF76 /* ASImageNode+AnimatedImagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||||
68B0277B1C1A79D60041016B /* ASDisplayNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
68B0277B1C1A79D60041016B /* ASDisplayNode+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
68B8A4E21CBDB958007E4543 /* ASWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
68B8A4E21CBDB958007E4543 /* ASWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
|
||||||
@ -667,6 +668,7 @@
|
|||||||
68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASImageContainerProtocolCategories.h; sourceTree = "<group>"; };
|
68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASImageContainerProtocolCategories.h; sourceTree = "<group>"; };
|
||||||
68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASImageContainerProtocolCategories.m; sourceTree = "<group>"; };
|
68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASImageContainerProtocolCategories.m; sourceTree = "<group>"; };
|
||||||
68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPINRemoteImageDownloader.h; sourceTree = "<group>"; };
|
68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPINRemoteImageDownloader.h; sourceTree = "<group>"; };
|
||||||
|
683F563620E409D600CEB7A3 /* ASDisplayNode+InterfaceState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+InterfaceState.h"; sourceTree = "<group>"; };
|
||||||
68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+Beta.h"; sourceTree = "<group>"; };
|
68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASDisplayNode+Beta.h"; sourceTree = "<group>"; };
|
||||||
68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASImageNode+AnimatedImagePrivate.h"; sourceTree = "<group>"; };
|
68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASImageNode+AnimatedImagePrivate.h"; sourceTree = "<group>"; };
|
||||||
68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASWeakProxy.h; sourceTree = "<group>"; };
|
68B8A4DF1CBDB958007E4543 /* ASWeakProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASWeakProxy.h; sourceTree = "<group>"; };
|
||||||
@ -1156,6 +1158,7 @@
|
|||||||
68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */,
|
68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */,
|
||||||
CC034A071E60BEB400626263 /* ASDisplayNode+Convenience.h */,
|
CC034A071E60BEB400626263 /* ASDisplayNode+Convenience.h */,
|
||||||
CC034A081E60BEB400626263 /* ASDisplayNode+Convenience.m */,
|
CC034A081E60BEB400626263 /* ASDisplayNode+Convenience.m */,
|
||||||
|
683F563620E409D600CEB7A3 /* ASDisplayNode+InterfaceState.h */,
|
||||||
69BCE3D71EC6513B007DCCAD /* ASDisplayNode+Layout.mm */,
|
69BCE3D71EC6513B007DCCAD /* ASDisplayNode+Layout.mm */,
|
||||||
058D09DA195D050800B7D73C /* ASDisplayNode+Subclasses.h */,
|
058D09DA195D050800B7D73C /* ASDisplayNode+Subclasses.h */,
|
||||||
90FC784E1E4BFE1B00383C5A /* ASDisplayNode+Yoga.mm */,
|
90FC784E1E4BFE1B00383C5A /* ASDisplayNode+Yoga.mm */,
|
||||||
@ -1915,6 +1918,7 @@
|
|||||||
CC034A091E60BEB400626263 /* ASDisplayNode+Convenience.h in Headers */,
|
CC034A091E60BEB400626263 /* ASDisplayNode+Convenience.h in Headers */,
|
||||||
254C6B7E1BF94DF4003EC431 /* ASTextKitTailTruncater.h in Headers */,
|
254C6B7E1BF94DF4003EC431 /* ASTextKitTailTruncater.h in Headers */,
|
||||||
B35062491B010EFD0018CF92 /* _ASCoreAnimationExtras.h in Headers */,
|
B35062491B010EFD0018CF92 /* _ASCoreAnimationExtras.h in Headers */,
|
||||||
|
683F563720E409D700CEB7A3 /* ASDisplayNode+InterfaceState.h in Headers */,
|
||||||
68EE0DBE1C1B4ED300BA1B99 /* ASMainSerialQueue.h in Headers */,
|
68EE0DBE1C1B4ED300BA1B99 /* ASMainSerialQueue.h in Headers */,
|
||||||
CCCCCCE11EC3EF060087FE10 /* ASTextUtilities.h in Headers */,
|
CCCCCCE11EC3EF060087FE10 /* ASTextUtilities.h in Headers */,
|
||||||
B350624B1B010EFD0018CF92 /* _ASPendingState.h in Headers */,
|
B350624B1B010EFD0018CF92 /* _ASPendingState.h in Headers */,
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
## master
|
## master
|
||||||
* Add your own contributions to the next release on the line below this with your name.
|
* Add your own contributions to the next release on the line below this with your name.
|
||||||
|
- [ASDisplayNode] Adds support for multiple interface state delegates. [Garrett Moon](https://github.com/garrettmoon) [#979](https://github.com/TextureGroup/Texture/pull/979)
|
||||||
- [ASDataController] Add capability to renew supplementary views (update map) when size change from zero to non-zero.[Max Wang](https://github.com/wsdwsd0829) [#842](https://github.com/TextureGroup/Texture/pull/842)
|
- [ASDataController] Add capability to renew supplementary views (update map) when size change from zero to non-zero.[Max Wang](https://github.com/wsdwsd0829) [#842](https://github.com/TextureGroup/Texture/pull/842)
|
||||||
- Make `ASPerformMainThreadDeallocation` visible in C. [Adlai Holler](https://github.com/Adlai-Holler)
|
- Make `ASPerformMainThreadDeallocation` visible in C. [Adlai Holler](https://github.com/Adlai-Holler)
|
||||||
- Add snapshot test for astextnode2. [Max Wang](https://github.com/wsdwsd0829) [#935](https://github.com/TextureGroup/Texture/pull/935)
|
- Add snapshot test for astextnode2. [Max Wang](https://github.com/wsdwsd0829) [#935](https://github.com/TextureGroup/Texture/pull/935)
|
||||||
|
|||||||
124
Source/ASDisplayNode+InterfaceState.h
Normal file
124
Source/ASDisplayNode+InterfaceState.h
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
//
|
||||||
|
// ASDisplayNode+InterfaceState.h
|
||||||
|
// Texture
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017-present, Pinterest, Inc. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface state is available on ASDisplayNode and ASViewController, and
|
||||||
|
* allows checking whether a node is in an interface situation where it is prudent to trigger certain
|
||||||
|
* actions: measurement, data loading, display, and visibility (the latter for animations or other onscreen-only effects).
|
||||||
|
*
|
||||||
|
* The defualt state, ASInterfaceStateNone, means that the element is not predicted to be onscreen soon and
|
||||||
|
* preloading should not be performed. Swift: use [] for the default behavior.
|
||||||
|
*/
|
||||||
|
typedef NS_OPTIONS(NSUInteger, ASInterfaceState)
|
||||||
|
{
|
||||||
|
/** The element is not predicted to be onscreen soon and preloading should not be performed */
|
||||||
|
ASInterfaceStateNone = 0,
|
||||||
|
/** The element may be added to a view soon that could become visible. Measure the layout, including size calculation. */
|
||||||
|
ASInterfaceStateMeasureLayout = 1 << 0,
|
||||||
|
/** The element is likely enough to come onscreen that disk and/or network data required for display should be fetched. */
|
||||||
|
ASInterfaceStatePreload = 1 << 1,
|
||||||
|
/** The element is very likely to become visible, and concurrent rendering should be executed for any -setNeedsDisplay. */
|
||||||
|
ASInterfaceStateDisplay = 1 << 2,
|
||||||
|
/** The element is physically onscreen by at least 1 pixel.
|
||||||
|
In practice, all other bit fields should also be set when this flag is set. */
|
||||||
|
ASInterfaceStateVisible = 1 << 3,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The node is not contained in a cell but it is in a window.
|
||||||
|
*
|
||||||
|
* Currently we only set `interfaceState` to other values for
|
||||||
|
* nodes contained in table views or collection views.
|
||||||
|
*/
|
||||||
|
ASInterfaceStateInHierarchy = ASInterfaceStateMeasureLayout | ASInterfaceStatePreload | ASInterfaceStateDisplay | ASInterfaceStateVisible,
|
||||||
|
};
|
||||||
|
|
||||||
|
@protocol ASInterfaceStateDelegate <NSObject>
|
||||||
|
@optional
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Called whenever any bit in the ASInterfaceState bitfield is changed.
|
||||||
|
* @discussion Subclasses may use this to monitor when they become visible, should free cached data, and much more.
|
||||||
|
* @see ASInterfaceState
|
||||||
|
*/
|
||||||
|
- (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfaceState)oldState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Called whenever the node becomes visible.
|
||||||
|
* @discussion Subclasses may use this to monitor when they become visible.
|
||||||
|
* @note This method is guaranteed to be called on main.
|
||||||
|
*/
|
||||||
|
- (void)didEnterVisibleState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Called whenever the node is no longer visible.
|
||||||
|
* @discussion Subclasses may use this to monitor when they are no longer visible.
|
||||||
|
* @note This method is guaranteed to be called on main.
|
||||||
|
*/
|
||||||
|
- (void)didExitVisibleState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Called whenever the the node has entered the display state.
|
||||||
|
* @discussion Subclasses may use this to monitor when a node should be rendering its content.
|
||||||
|
* @note This method is guaranteed to be called on main.
|
||||||
|
*/
|
||||||
|
- (void)didEnterDisplayState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Called whenever the the node has exited the display state.
|
||||||
|
* @discussion Subclasses may use this to monitor when a node should no longer be rendering its content.
|
||||||
|
* @note This method is guaranteed to be called on main.
|
||||||
|
*/
|
||||||
|
- (void)didExitDisplayState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Called whenever the the node has entered the preload state.
|
||||||
|
* @discussion Subclasses may use this to monitor data for a node should be preloaded, either from a local or remote source.
|
||||||
|
* @note This method is guaranteed to be called on main.
|
||||||
|
*/
|
||||||
|
- (void)didEnterPreloadState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Called whenever the the node has exited the preload state.
|
||||||
|
* @discussion Subclasses may use this to monitor whether preloading data for a node should be canceled.
|
||||||
|
* @note This method is guaranteed to be called on main.
|
||||||
|
*/
|
||||||
|
- (void)didExitPreloadState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Called when the node has completed applying the layout.
|
||||||
|
* @discussion Can be used for operations that are performed after layout has completed.
|
||||||
|
* @note This method is guaranteed to be called on main.
|
||||||
|
*/
|
||||||
|
- (void)nodeDidLayout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Called when the node loads.
|
||||||
|
* @discussion Can be used for operations that are performed after the node's view is available.
|
||||||
|
* @note This method is guaranteed to be called on main.
|
||||||
|
*/
|
||||||
|
- (void)nodeDidLoad;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Indicates that the receiver and all subnodes have finished displaying.
|
||||||
|
* @discussion May be called more than once, for example if the receiver has a network image node.
|
||||||
|
* This is called after the first display pass even if network image nodes have not downloaded anything
|
||||||
|
* (text would be done, and other nodes that are ready to do their final display). Each render of
|
||||||
|
* every progressive jpeg network node would cause this to be called, so this hook could be called up to
|
||||||
|
* 1 + (pJPEGcount * pJPEGrenderCount) times. The render count depends on how many times the downloader calls
|
||||||
|
* the progressImage block.
|
||||||
|
* @note This method is guaranteed to be called on main.
|
||||||
|
*/
|
||||||
|
- (void)hierarchyDisplayDidFinish;
|
||||||
|
|
||||||
|
@end
|
||||||
@ -42,74 +42,6 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
* variables.
|
* variables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@protocol ASInterfaceStateDelegate <NSObject>
|
|
||||||
@required
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Called whenever any bit in the ASInterfaceState bitfield is changed.
|
|
||||||
* @discussion Subclasses may use this to monitor when they become visible, should free cached data, and much more.
|
|
||||||
* @see ASInterfaceState
|
|
||||||
*/
|
|
||||||
- (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfaceState)oldState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Called whenever the node becomes visible.
|
|
||||||
* @discussion Subclasses may use this to monitor when they become visible.
|
|
||||||
* @note This method is guaranteed to be called on main.
|
|
||||||
*/
|
|
||||||
- (void)didEnterVisibleState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Called whenever the node is no longer visible.
|
|
||||||
* @discussion Subclasses may use this to monitor when they are no longer visible.
|
|
||||||
* @note This method is guaranteed to be called on main.
|
|
||||||
*/
|
|
||||||
- (void)didExitVisibleState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Called whenever the the node has entered the display state.
|
|
||||||
* @discussion Subclasses may use this to monitor when a node should be rendering its content.
|
|
||||||
* @note This method is guaranteed to be called on main.
|
|
||||||
*/
|
|
||||||
- (void)didEnterDisplayState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Called whenever the the node has exited the display state.
|
|
||||||
* @discussion Subclasses may use this to monitor when a node should no longer be rendering its content.
|
|
||||||
* @note This method is guaranteed to be called on main.
|
|
||||||
*/
|
|
||||||
- (void)didExitDisplayState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Called whenever the the node has entered the preload state.
|
|
||||||
* @discussion Subclasses may use this to monitor data for a node should be preloaded, either from a local or remote source.
|
|
||||||
* @note This method is guaranteed to be called on main.
|
|
||||||
*/
|
|
||||||
- (void)didEnterPreloadState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Called whenever the the node has exited the preload state.
|
|
||||||
* @discussion Subclasses may use this to monitor whether preloading data for a node should be canceled.
|
|
||||||
* @note This method is guaranteed to be called on main.
|
|
||||||
*/
|
|
||||||
- (void)didExitPreloadState;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Called when the node has completed applying the layout.
|
|
||||||
* @discussion Can be used for operations that are performed after layout has completed.
|
|
||||||
* @note This method is guaranteed to be called on main.
|
|
||||||
*/
|
|
||||||
- (void)nodeDidLayout;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @abstract Called when the node loads.
|
|
||||||
* @discussion Can be used for operations that are performed after the node's view is available.
|
|
||||||
* @note This method is guaranteed to be called on main.
|
|
||||||
*/
|
|
||||||
- (void)nodeDidLoad;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface ASDisplayNode (Subclassing) <ASInterfaceStateDelegate>
|
@interface ASDisplayNode (Subclassing) <ASInterfaceStateDelegate>
|
||||||
|
|
||||||
#pragma mark - Properties
|
#pragma mark - Properties
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
#import <AsyncDisplayKit/_ASAsyncTransactionContainer.h>
|
#import <AsyncDisplayKit/_ASAsyncTransactionContainer.h>
|
||||||
#import <AsyncDisplayKit/ASBaseDefines.h>
|
#import <AsyncDisplayKit/ASBaseDefines.h>
|
||||||
#import <AsyncDisplayKit/ASDimension.h>
|
#import <AsyncDisplayKit/ASDimension.h>
|
||||||
|
#import <AsyncDisplayKit/ASDisplayNode+InterfaceState.h>
|
||||||
#import <AsyncDisplayKit/ASAsciiArtBoxCreator.h>
|
#import <AsyncDisplayKit/ASAsciiArtBoxCreator.h>
|
||||||
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
|
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
|
||||||
#import <AsyncDisplayKit/ASLayoutElement.h>
|
#import <AsyncDisplayKit/ASLayoutElement.h>
|
||||||
@ -70,37 +71,6 @@ typedef ASLayoutSpec * _Nonnull(^ASLayoutSpecBlock)(__kindof ASDisplayNode *node
|
|||||||
*/
|
*/
|
||||||
typedef void (^ASDisplayNodeNonFatalErrorBlock)(NSError *error);
|
typedef void (^ASDisplayNodeNonFatalErrorBlock)(NSError *error);
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface state is available on ASDisplayNode and ASViewController, and
|
|
||||||
* allows checking whether a node is in an interface situation where it is prudent to trigger certain
|
|
||||||
* actions: measurement, data loading, display, and visibility (the latter for animations or other onscreen-only effects).
|
|
||||||
*
|
|
||||||
* The defualt state, ASInterfaceStateNone, means that the element is not predicted to be onscreen soon and
|
|
||||||
* preloading should not be performed. Swift: use [] for the default behavior.
|
|
||||||
*/
|
|
||||||
typedef NS_OPTIONS(NSUInteger, ASInterfaceState)
|
|
||||||
{
|
|
||||||
/** The element is not predicted to be onscreen soon and preloading should not be performed */
|
|
||||||
ASInterfaceStateNone = 0,
|
|
||||||
/** The element may be added to a view soon that could become visible. Measure the layout, including size calculation. */
|
|
||||||
ASInterfaceStateMeasureLayout = 1 << 0,
|
|
||||||
/** The element is likely enough to come onscreen that disk and/or network data required for display should be fetched. */
|
|
||||||
ASInterfaceStatePreload = 1 << 1,
|
|
||||||
/** The element is very likely to become visible, and concurrent rendering should be executed for any -setNeedsDisplay. */
|
|
||||||
ASInterfaceStateDisplay = 1 << 2,
|
|
||||||
/** The element is physically onscreen by at least 1 pixel.
|
|
||||||
In practice, all other bit fields should also be set when this flag is set. */
|
|
||||||
ASInterfaceStateVisible = 1 << 3,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The node is not contained in a cell but it is in a window.
|
|
||||||
*
|
|
||||||
* Currently we only set `interfaceState` to other values for
|
|
||||||
* nodes contained in table views or collection views.
|
|
||||||
*/
|
|
||||||
ASInterfaceStateInHierarchy = ASInterfaceStateMeasureLayout | ASInterfaceStatePreload | ASInterfaceStateDisplay | ASInterfaceStateVisible,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef NS_ENUM(NSInteger, ASCornerRoundingType) {
|
typedef NS_ENUM(NSInteger, ASCornerRoundingType) {
|
||||||
ASCornerRoundingTypeDefaultSlowCALayer,
|
ASCornerRoundingTypeDefaultSlowCALayer,
|
||||||
ASCornerRoundingTypePrecomposited,
|
ASCornerRoundingTypePrecomposited,
|
||||||
@ -292,6 +262,24 @@ AS_EXTERN NSInteger const ASDefaultDrawingPriority;
|
|||||||
*/
|
*/
|
||||||
@property (readonly) ASInterfaceState interfaceState;
|
@property (readonly) ASInterfaceState interfaceState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Adds a delegate to receive notifications on interfaceState changes.
|
||||||
|
*
|
||||||
|
* @warning This must be called from the main thread.
|
||||||
|
*
|
||||||
|
* @see ASInterfaceState
|
||||||
|
*/
|
||||||
|
- (void)addInterfaceStateDelegate:(id <ASInterfaceStateDelegate>)interfaceStateDelegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @abstract Removes a delegate from receiving notifications on interfaceState changes.
|
||||||
|
*
|
||||||
|
* @warning This must be called from the main thread.
|
||||||
|
*
|
||||||
|
* @see ASInterfaceState
|
||||||
|
*/
|
||||||
|
- (void)removeInterfaceStateDelegate:(id <ASInterfaceStateDelegate>)interfaceStateDelegate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @abstract Class property that allows to set a block that can be called on non-fatal errors. This
|
* @abstract Class property that allows to set a block that can be called on non-fatal errors. This
|
||||||
* property can be useful for cases when Async Display Kit can recover from an abnormal behavior, but
|
* property can be useful for cases when Async Display Kit can recover from an abnormal behavior, but
|
||||||
|
|||||||
@ -36,6 +36,7 @@
|
|||||||
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>
|
#import <AsyncDisplayKit/ASDisplayNodeExtras.h>
|
||||||
#import <AsyncDisplayKit/ASDisplayNodeInternal.h>
|
#import <AsyncDisplayKit/ASDisplayNodeInternal.h>
|
||||||
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
|
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
|
||||||
|
#import <AsyncDisplayKit/ASDisplayNode+InterfaceState.h>
|
||||||
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
|
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
|
||||||
#import <AsyncDisplayKit/ASEqualityHelpers.h>
|
#import <AsyncDisplayKit/ASEqualityHelpers.h>
|
||||||
#import <AsyncDisplayKit/ASGraphicsContext.h>
|
#import <AsyncDisplayKit/ASGraphicsContext.h>
|
||||||
@ -71,7 +72,6 @@ NSInteger const ASDefaultDrawingPriority = ASDefaultTransactionPriority;
|
|||||||
@protocol CALayerDelegate;
|
@protocol CALayerDelegate;
|
||||||
|
|
||||||
@interface ASDisplayNode () <UIGestureRecognizerDelegate, CALayerDelegate, _ASDisplayLayerDelegate, ASCATransactionQueueObserving>
|
@interface ASDisplayNode () <UIGestureRecognizerDelegate, CALayerDelegate, _ASDisplayLayerDelegate, ASCATransactionQueueObserving>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See ASDisplayNodeInternal.h for ivars
|
* See ASDisplayNodeInternal.h for ivars
|
||||||
*/
|
*/
|
||||||
@ -544,7 +544,11 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__);
|
|||||||
block(self);
|
block(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
[_interfaceStateDelegate nodeDidLoad];
|
for (id <ASInterfaceStateDelegate> delegate in _interfaceStateDelegates) {
|
||||||
|
if ([delegate respondsToSelector:@selector(nodeDidLoad)]) {
|
||||||
|
[delegate nodeDidLoad];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didLoad
|
- (void)didLoad
|
||||||
@ -1225,7 +1229,11 @@ ASSynthesizeLockingMethodsWithMutex(__instanceLock__);
|
|||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
||||||
ASDisplayNodeAssertTrue(self.isNodeLoaded);
|
ASDisplayNodeAssertTrue(self.isNodeLoaded);
|
||||||
[_interfaceStateDelegate nodeDidLayout];
|
for (id <ASInterfaceStateDelegate> delegate in _interfaceStateDelegates) {
|
||||||
|
if ([delegate respondsToSelector:@selector(nodeDidLayout)]) {
|
||||||
|
[delegate nodeDidLayout];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark Layout Transition
|
#pragma mark Layout Transition
|
||||||
@ -1447,6 +1455,13 @@ NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"AS
|
|||||||
if (_pendingDisplayNodes.isEmpty) {
|
if (_pendingDisplayNodes.isEmpty) {
|
||||||
|
|
||||||
[self hierarchyDisplayDidFinish];
|
[self hierarchyDisplayDidFinish];
|
||||||
|
|
||||||
|
for (id <ASInterfaceStateDelegate> delegate in _interfaceStateDelegates) {
|
||||||
|
if ([delegate respondsToSelector:@selector(hierarchyDisplayDidFinish)]) {
|
||||||
|
[delegate hierarchyDisplayDidFinish];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BOOL placeholderShouldPersist = [self placeholderShouldPersist];
|
BOOL placeholderShouldPersist = [self placeholderShouldPersist];
|
||||||
|
|
||||||
__instanceLock__.lock();
|
__instanceLock__.lock();
|
||||||
@ -3142,7 +3157,12 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
|
|||||||
{
|
{
|
||||||
// Subclass hook
|
// Subclass hook
|
||||||
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
||||||
[_interfaceStateDelegate interfaceStateDidChange:newState fromState:oldState];
|
ASDisplayNodeAssertMainThread();
|
||||||
|
for (id <ASInterfaceStateDelegate> delegate in _interfaceStateDelegates) {
|
||||||
|
if ([delegate respondsToSelector:@selector(interfaceStateDidChange:fromState:)]) {
|
||||||
|
[delegate interfaceStateDidChange:newState fromState:oldState];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)shouldScheduleDisplayWithNewInterfaceState:(ASInterfaceState)newInterfaceState
|
- (BOOL)shouldScheduleDisplayWithNewInterfaceState:(ASInterfaceState)newInterfaceState
|
||||||
@ -3152,6 +3172,24 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
|
|||||||
return willDisplay && (willDisplay != nowDisplay);
|
return willDisplay && (willDisplay != nowDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)addInterfaceStateDelegate:(id <ASInterfaceStateDelegate>)interfaceStateDelegate
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
|
||||||
|
// Not a fan of lazy loading, but this method won't get called very often and avoiding
|
||||||
|
// the overhead of creating this is probably worth it.
|
||||||
|
if (_interfaceStateDelegates == nil) {
|
||||||
|
_interfaceStateDelegates = [NSHashTable weakObjectsHashTable];
|
||||||
|
}
|
||||||
|
[_interfaceStateDelegates addObject:interfaceStateDelegate];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)removeInterfaceStateDelegate:(id <ASInterfaceStateDelegate>)interfaceStateDelegate
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
[_interfaceStateDelegates removeObject:interfaceStateDelegate];
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)isVisible
|
- (BOOL)isVisible
|
||||||
{
|
{
|
||||||
ASDN::MutexLocker l(__instanceLock__);
|
ASDN::MutexLocker l(__instanceLock__);
|
||||||
@ -3163,7 +3201,11 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
|
|||||||
// subclass override
|
// subclass override
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
||||||
[_interfaceStateDelegate didEnterVisibleState];
|
for (id <ASInterfaceStateDelegate> delegate in _interfaceStateDelegates) {
|
||||||
|
if ([delegate respondsToSelector:@selector(didEnterVisibleState)]) {
|
||||||
|
[delegate didEnterVisibleState];
|
||||||
|
}
|
||||||
|
}
|
||||||
#if AS_ENABLE_TIPS
|
#if AS_ENABLE_TIPS
|
||||||
[ASTipsController.shared nodeDidAppear:self];
|
[ASTipsController.shared nodeDidAppear:self];
|
||||||
#endif
|
#endif
|
||||||
@ -3174,7 +3216,11 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
|
|||||||
// subclass override
|
// subclass override
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
||||||
[_interfaceStateDelegate didExitVisibleState];
|
for (id <ASInterfaceStateDelegate> delegate in _interfaceStateDelegates) {
|
||||||
|
if ([delegate respondsToSelector:@selector(didExitVisibleState)]) {
|
||||||
|
[delegate didExitVisibleState];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isInDisplayState
|
- (BOOL)isInDisplayState
|
||||||
@ -3188,7 +3234,11 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
|
|||||||
// subclass override
|
// subclass override
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
||||||
[_interfaceStateDelegate didEnterDisplayState];
|
for (id <ASInterfaceStateDelegate> delegate in _interfaceStateDelegates) {
|
||||||
|
if ([delegate respondsToSelector:@selector(didEnterDisplayState)]) {
|
||||||
|
[delegate didEnterDisplayState];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didExitDisplayState
|
- (void)didExitDisplayState
|
||||||
@ -3196,7 +3246,11 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
|
|||||||
// subclass override
|
// subclass override
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
||||||
[_interfaceStateDelegate didExitDisplayState];
|
for (id <ASInterfaceStateDelegate> delegate in _interfaceStateDelegates) {
|
||||||
|
if ([delegate respondsToSelector:@selector(didExitDisplayState)]) {
|
||||||
|
[delegate didExitDisplayState];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isInPreloadState
|
- (BOOL)isInPreloadState
|
||||||
@ -3247,14 +3301,22 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
|
|||||||
[self layoutIfNeeded];
|
[self layoutIfNeeded];
|
||||||
}
|
}
|
||||||
|
|
||||||
[_interfaceStateDelegate didEnterPreloadState];
|
for (id <ASInterfaceStateDelegate> delegate in _interfaceStateDelegates) {
|
||||||
|
if ([delegate respondsToSelector:@selector(didEnterPreloadState)]) {
|
||||||
|
[delegate didEnterPreloadState];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didExitPreloadState
|
- (void)didExitPreloadState
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
ASDisplayNodeAssertLockUnownedByCurrentThread(__instanceLock__);
|
||||||
[_interfaceStateDelegate didExitPreloadState];
|
for (id <ASInterfaceStateDelegate> delegate in _interfaceStateDelegates) {
|
||||||
|
if ([delegate respondsToSelector:@selector(didExitPreloadState)]) {
|
||||||
|
[delegate didExitPreloadState];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)clearContents
|
- (void)clearContents
|
||||||
|
|||||||
@ -15,9 +15,10 @@
|
|||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <AsyncDisplayKit/ASWeakProxy.h>
|
#import <AsyncDisplayKit/ASInternalHelpers.h>
|
||||||
#import <AsyncDisplayKit/ASNodeController+Beta.h>
|
|
||||||
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
|
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
|
||||||
|
#import <AsyncDisplayKit/ASNodeController+Beta.h>
|
||||||
|
#import <AsyncDisplayKit/ASWeakProxy.h>
|
||||||
|
|
||||||
#define _node (_shouldInvertStrongReference ? _weakNode : _strongNode)
|
#define _node (_shouldInvertStrongReference ? _weakNode : _strongNode)
|
||||||
|
|
||||||
@ -74,7 +75,7 @@
|
|||||||
_weakNode = nil;
|
_weakNode = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
node.interfaceStateDelegate = self;
|
[node addInterfaceStateDelegate:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setNode:(ASDisplayNode *)node
|
- (void)setNode:(ASDisplayNode *)node
|
||||||
|
|||||||
@ -138,9 +138,6 @@ __unused static NSString * _Nonnull NSStringFromASHierarchyStateChange(ASHierarc
|
|||||||
// Returns the bounds of the node without reaching the view or layer
|
// Returns the bounds of the node without reaching the view or layer
|
||||||
- (CGRect)_locked_threadSafeBounds;
|
- (CGRect)_locked_threadSafeBounds;
|
||||||
|
|
||||||
// delegate to inform of ASInterfaceState changes (used by ASNodeController)
|
|
||||||
@property (nonatomic, weak) id<ASInterfaceStateDelegate> interfaceStateDelegate;
|
|
||||||
|
|
||||||
// The -pendingInterfaceState holds the value that will be applied to -interfaceState by the
|
// The -pendingInterfaceState holds the value that will be applied to -interfaceState by the
|
||||||
// ASCATransactionQueue. If already applied, it matches -interfaceState. Thread-safe access.
|
// ASCATransactionQueue. If already applied, it matches -interfaceState. Thread-safe access.
|
||||||
@property (nonatomic, readonly) ASInterfaceState pendingInterfaceState;
|
@property (nonatomic, readonly) ASInterfaceState pendingInterfaceState;
|
||||||
|
|||||||
@ -241,6 +241,8 @@ AS_EXTERN NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimest
|
|||||||
NSTimeInterval _debugTimeToAddSubnodeViews;
|
NSTimeInterval _debugTimeToAddSubnodeViews;
|
||||||
NSTimeInterval _debugTimeForDidLoad;
|
NSTimeInterval _debugTimeForDidLoad;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
NSHashTable <id <ASInterfaceStateDelegate>> *_interfaceStateDelegates;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)scheduleNodeForRecursiveDisplay:(ASDisplayNode *)node;
|
+ (void)scheduleNodeForRecursiveDisplay:(ASDisplayNode *)node;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user