mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-09 22:20:41 +00:00
API in ASDataController. Move allocations and loaded node layouts to occur during batch layout phase.
508 lines
20 KiB
Objective-C
508 lines
20 KiB
Objective-C
/* 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 <UIKit/UIKit.h>
|
|
|
|
#import <AsyncDisplayKit/ASRangeController.h>
|
|
#import <AsyncDisplayKit/ASCollectionViewProtocols.h>
|
|
#import <AsyncDisplayKit/ASBaseDefines.h>
|
|
#import <AsyncDisplayKit/ASBatchContext.h>
|
|
#import <AsyncDisplayKit/ASCollectionViewFlowLayoutInspector.h>
|
|
|
|
@class ASCellNode;
|
|
@class ASCollectionNode;
|
|
@protocol ASCollectionDataSource;
|
|
@protocol ASCollectionDelegate;
|
|
@protocol ASCollectionViewLayoutInspecting;
|
|
@protocol ASCollectionViewLayoutFacilitatorProtocol;
|
|
|
|
NS_ASSUME_NONNULL_BEGIN
|
|
|
|
/**
|
|
* Asynchronous UICollectionView with Intelligent Preloading capabilities.
|
|
*
|
|
* ASCollectionNode is recommended over ASCollectionView. This class exists for adoption convenience.
|
|
*
|
|
* ASCollectionView is a true subclass of UICollectionView, meaning it is pointer-compatible
|
|
* with code that currently uses UICollectionView.
|
|
*
|
|
* The main difference is that asyncDataSource expects -nodeForItemAtIndexPath, an ASCellNode, and
|
|
* the sizeForItemAtIndexPath: method is eliminated (as are the performance problems caused by it).
|
|
* This is made possible because ASCellNodes can calculate their own size, and preload ahead of time.
|
|
*/
|
|
@interface ASCollectionView : UICollectionView
|
|
|
|
/**
|
|
* Initializer.
|
|
*
|
|
* @param layout The layout object to use for organizing items. The collection view stores a strong reference to the specified object. Must not be nil.
|
|
*/
|
|
- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout;
|
|
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
|
|
|
|
// The corresponding ASCollectionNode, which exists even if directly allocating & handling the view class.
|
|
@property (nonatomic, weak, readonly) ASCollectionNode *collectionNode;
|
|
|
|
@property (nonatomic, weak) id<ASCollectionDelegate> asyncDelegate;
|
|
@property (nonatomic, weak) id<ASCollectionDataSource> asyncDataSource;
|
|
|
|
/**
|
|
* Tuning parameters for a range type in full mode.
|
|
*
|
|
* @param rangeType The range type to get the tuning parameters for.
|
|
*
|
|
* @returns A tuning parameter value for the given range type in full mode.
|
|
*
|
|
* @see ASLayoutRangeMode
|
|
* @see ASLayoutRangeType
|
|
*/
|
|
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType;
|
|
|
|
/**
|
|
* Set the tuning parameters for a range type in full mode.
|
|
*
|
|
* @param tuningParameters The tuning parameters to store for a range type.
|
|
* @param rangeType The range type to set the tuning parameters for.
|
|
*
|
|
* @see ASLayoutRangeMode
|
|
* @see ASLayoutRangeType
|
|
*/
|
|
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType;
|
|
|
|
/**
|
|
* Tuning parameters for a range type in the specified mode.
|
|
*
|
|
* @param rangeMode The range mode to get the runing parameters for.
|
|
* @param rangeType The range type to get the tuning parameters for.
|
|
*
|
|
* @returns A tuning parameter value for the given range type in the given mode.
|
|
*
|
|
* @see ASLayoutRangeMode
|
|
* @see ASLayoutRangeType
|
|
*/
|
|
- (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType;
|
|
|
|
/**
|
|
* Set the tuning parameters for a range type in the specigied mode.
|
|
*
|
|
* @param tuningParameters The tuning parameters to store for a range type.
|
|
* @param rangeMode The range mode to set the runing parameters for.
|
|
* @param rangeType The range type to set the tuning parameters for.
|
|
*
|
|
* @see ASLayoutRangeMode
|
|
* @see ASLayoutRangeType
|
|
*/
|
|
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType;
|
|
|
|
/**
|
|
* The number of screens left to scroll before the delegate -collectionView:beginBatchFetchingWithContext: is called.
|
|
*
|
|
* Defaults to one screenful.
|
|
*/
|
|
@property (nonatomic, assign) CGFloat leadingScreensForBatching;
|
|
|
|
/**
|
|
* Optional introspection object for the collection view's layout.
|
|
*
|
|
* @discussion Since supplementary and decoration views are controlled by the collection view's layout, this object
|
|
* is used as a bridge to provide information to the internal data controller about the existence of these views and
|
|
* their associated index paths. For collection views using `UICollectionViewFlowLayout`, a default inspector
|
|
* implementation `ASCollectionViewFlowLayoutInspector` is created and set on this property by default. Custom
|
|
* collection view layout subclasses will need to provide their own implementation of an inspector object for their
|
|
* supplementary views to be compatible with `ASCollectionView`'s supplementary node support.
|
|
*/
|
|
@property (nonatomic, weak) id<ASCollectionViewLayoutInspecting> layoutInspector;
|
|
|
|
/**
|
|
* Perform a batch of updates asynchronously, optionally disabling all animations in the batch. This method must be called from the main thread.
|
|
* The asyncDataSource must be updated to reflect the changes before the update block completes.
|
|
*
|
|
* @param animated NO to disable animations for this batch
|
|
* @param updates The block that performs the relevant insert, delete, reload, or move operations.
|
|
* @param completion A completion handler block to execute when all of the operations are finished. This block takes a single
|
|
* Boolean parameter that contains the value YES if all of the related animations completed successfully or
|
|
* NO if they were interrupted. This parameter may be nil. If supplied, the block is run on the main thread.
|
|
*/
|
|
- (void)performBatchAnimated:(BOOL)animated updates:(void (^ _Nullable)())updates completion:(void (^ _Nullable)(BOOL))completion;
|
|
|
|
/**
|
|
* Perform a batch of updates asynchronously. This method must be called from the main thread.
|
|
* The asyncDataSource must be updated to reflect the changes before update block completes.
|
|
*
|
|
* @param updates The block that performs the relevant insert, delete, reload, or move operations.
|
|
* @param completion A completion handler block to execute when all of the operations are finished. This block takes a single
|
|
* Boolean parameter that contains the value YES if all of the related animations completed successfully or
|
|
* NO if they were interrupted. This parameter may be nil. If supplied, the block is run on the main thread.
|
|
*/
|
|
- (void)performBatchUpdates:(void (^ _Nullable)())updates completion:(void (^ _Nullable)(BOOL))completion;
|
|
|
|
/**
|
|
* Reload everything from scratch, destroying the working range and all cached nodes.
|
|
*
|
|
* @param completion block to run on completion of asynchronous loading or nil. If supplied, the block is run on
|
|
* the main thread.
|
|
* @warning This method is substantially more expensive than UICollectionView's version.
|
|
*/
|
|
- (void)reloadDataWithCompletion:(void (^ _Nullable)())completion;
|
|
|
|
/**
|
|
* Reload everything from scratch, destroying the working range and all cached nodes.
|
|
*
|
|
* @warning This method is substantially more expensive than UICollectionView's version.
|
|
*/
|
|
- (void)reloadData;
|
|
|
|
/**
|
|
* Reload everything from scratch entirely on the main thread, destroying the working range and all cached nodes.
|
|
*
|
|
* @warning This method is substantially more expensive than UICollectionView's version and will block the main thread
|
|
* while all the cells load.
|
|
*/
|
|
- (void)reloadDataImmediately;
|
|
|
|
/**
|
|
* Registers the given kind of supplementary node for use in creating node-backed supplementary views.
|
|
*
|
|
* @param kind The kind of supplementary node that will be requested through the data source.
|
|
*
|
|
* @discussion Use this method to register support for the use of supplementary nodes in place of the default
|
|
* `registerClass:forSupplementaryViewOfKind:withReuseIdentifier:` and `registerNib:forSupplementaryViewOfKind:withReuseIdentifier:`
|
|
* methods. This method will register an internal backing view that will host the contents of the supplementary nodes
|
|
* returned from the data source.
|
|
*/
|
|
- (void)registerSupplementaryNodeOfKind:(NSString *)elementKind;
|
|
|
|
/**
|
|
* Inserts one or more sections.
|
|
*
|
|
* @param sections An index set that specifies the sections to insert.
|
|
*
|
|
* @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes
|
|
* before this method is called.
|
|
*/
|
|
- (void)insertSections:(NSIndexSet *)sections;
|
|
|
|
/**
|
|
* Deletes one or more sections.
|
|
*
|
|
* @param sections An index set that specifies the sections to delete.
|
|
*
|
|
* @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes
|
|
* before this method is called.
|
|
*/
|
|
- (void)deleteSections:(NSIndexSet *)sections;
|
|
|
|
/**
|
|
* Reloads the specified sections.
|
|
*
|
|
* @param sections An index set that specifies the sections to reload.
|
|
*
|
|
* @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes
|
|
* before this method is called.
|
|
*/
|
|
- (void)reloadSections:(NSIndexSet *)sections;
|
|
|
|
/**
|
|
* Moves a section to a new location.
|
|
*
|
|
* @param section The index of the section to move.
|
|
*
|
|
* @param newSection The index that is the destination of the move for the section.
|
|
*
|
|
* @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes
|
|
* before this method is called.
|
|
*/
|
|
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;
|
|
|
|
/**
|
|
* Inserts items at the locations identified by an array of index paths.
|
|
*
|
|
* @param indexPaths An array of NSIndexPath objects, each representing an item index and section index that together identify an item.
|
|
*
|
|
* @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes
|
|
* before this method is called.
|
|
*/
|
|
- (void)insertItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
|
|
|
|
/**
|
|
* Deletes the items specified by an array of index paths.
|
|
*
|
|
* @param indexPaths An array of NSIndexPath objects identifying the items to delete.
|
|
*
|
|
* @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes
|
|
* before this method is called.
|
|
*/
|
|
- (void)deleteItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
|
|
|
|
/**
|
|
* Reloads the specified items.
|
|
*
|
|
* @param indexPaths An array of NSIndexPath objects identifying the items to reload.
|
|
*
|
|
* @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes
|
|
* before this method is called.
|
|
*/
|
|
- (void)reloadItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
|
|
|
|
/**
|
|
* Moves the item at a specified location to a destination location.
|
|
*
|
|
* @param indexPath The index path identifying the item to move.
|
|
*
|
|
* @param newIndexPath The index path that is the destination of the move for the item.
|
|
*
|
|
* @discussion This method must be called from the main thread. The asyncDataSource must be updated to reflect the changes
|
|
* before this method is called.
|
|
*/
|
|
- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;
|
|
|
|
/**
|
|
* Similar to -cellForItemAtIndexPath:.
|
|
*
|
|
* @param indexPath The index path of the requested node.
|
|
*
|
|
* @returns a node for display at this indexpath.
|
|
*/
|
|
- (ASCellNode *)nodeForItemAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
/**
|
|
* Similar to -indexPathForCell:.
|
|
*
|
|
* @param cellNode a cellNode part of the table view
|
|
*
|
|
* @returns an indexPath for this cellNode
|
|
*/
|
|
- (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode;
|
|
|
|
/**
|
|
* Similar to -visibleCells.
|
|
*
|
|
* @returns an array containing the nodes being displayed on screen.
|
|
*/
|
|
- (NSArray<ASCellNode *> *)visibleNodes;
|
|
|
|
/**
|
|
* Query the sized node at `indexPath` for its calculatedSize.
|
|
*
|
|
* @param indexPath The index path for the node of interest.
|
|
*/
|
|
- (CGSize)calculatedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
/**
|
|
* Determines collection view's current scroll direction. Supports 2-axis collection views.
|
|
*
|
|
* @returns a bitmask of ASScrollDirection values.
|
|
*/
|
|
- (ASScrollDirection)scrollDirection;
|
|
|
|
/**
|
|
* Determines collection view's scrollable directions.
|
|
*
|
|
* @returns a bitmask of ASScrollDirection values.
|
|
*/
|
|
- (ASScrollDirection)scrollableDirections;
|
|
|
|
/**
|
|
* Triggers all loaded ASCellNodes to destroy displayed contents (freeing a lot of memory).
|
|
*
|
|
* @discussion This method should only be called by ASCollectionNode. To be removed in a later release.
|
|
*/
|
|
- (void)clearContents;
|
|
|
|
/**
|
|
* Triggers all loaded ASCellNodes to purge any data fetched from the network or disk (freeing memory).
|
|
*
|
|
* @discussion This method should only be called by ASCollectionNode. To be removed in a later release.
|
|
*/
|
|
- (void)clearFetchedData;
|
|
|
|
/**
|
|
* Forces the .contentInset to be UIEdgeInsetsZero.
|
|
*
|
|
* @discussion By default, UIKit sets the top inset to the navigation bar height, even for horizontally
|
|
* scrolling views. This can only be disabled by setting a property on the containing UIViewController,
|
|
* automaticallyAdjustsScrollViewInsets, which may not be accessible. ASPagerNode uses this to ensure
|
|
* its flow layout behaves predictably and does not log undefined layout warnings.
|
|
*/
|
|
@property (nonatomic) BOOL zeroContentInsets;
|
|
|
|
@end
|
|
|
|
|
|
/**
|
|
* This is a node-based UICollectionViewDataSource.
|
|
*/
|
|
#define ASCollectionViewDataSource ASCollectionDataSource
|
|
@protocol ASCollectionDataSource <ASCommonCollectionViewDataSource, NSObject>
|
|
|
|
/**
|
|
* Similar to -collectionView:cellForItemAtIndexPath:.
|
|
*
|
|
* @param collectionView The sender.
|
|
*
|
|
* @param indexPath The index path of the requested node.
|
|
*
|
|
* @returns a node for display at this indexpath. This will be called on the main thread and should not implement reuse (it will be called once per row). Unlike UICollectionView's version, this method
|
|
* is not called when the row is about to display.
|
|
*/
|
|
- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForItemAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
|
|
@optional
|
|
|
|
/**
|
|
*
|
|
* @param collectionView The sender.
|
|
*
|
|
* @param indexPath The index path of the requested node.
|
|
*
|
|
* @returns a block that creates the node for display at this indexpath. Must be thread-safe (can be called on the main thread or a background
|
|
* queue) and should not implement reuse (it will be called once per row).
|
|
*/
|
|
- (ASDataControllerCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
/**
|
|
* Asks the collection view to provide a supplementary node to display in the collection view.
|
|
*
|
|
* @param collectionView An object representing the collection view requesting this information.
|
|
* @param kind The kind of supplementary node to provide.
|
|
* @param indexPath The index path that specifies the location of the new supplementary node.
|
|
*/
|
|
- (ASCellNode *)collectionView:(ASCollectionView *)collectionView nodeForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
/**
|
|
* Provides the constrained size range for measuring the node at the index path.
|
|
*
|
|
* @param collectionView The sender.
|
|
*
|
|
* @param indexPath The index path of the node.
|
|
*
|
|
* @returns A constrained size range for layout the node at this index path.
|
|
*/
|
|
- (ASSizeRange)collectionView:(ASCollectionView *)collectionView constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
/**
|
|
* Indicator to lock the data source for data fetching in async mode.
|
|
* We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistence or exception
|
|
* due to the data access in async mode.
|
|
*
|
|
* @param collectionView The sender.
|
|
*/
|
|
- (void)collectionViewLockDataSource:(ASCollectionView *)collectionView;
|
|
|
|
/**
|
|
* Indicator to unlock the data source for data fetching in async mode.
|
|
* We should not update the data source until the data source has been unlocked. Otherwise, it will incur data inconsistence or exception
|
|
* due to the data access in async mode.
|
|
*
|
|
* @param collectionView The sender.
|
|
*/
|
|
- (void)collectionViewUnlockDataSource:(ASCollectionView *)collectionView;
|
|
|
|
@end
|
|
|
|
|
|
/**
|
|
* This is a node-based UICollectionViewDelegate.
|
|
*/
|
|
#define ASCollectionViewDelegate ASCollectionDelegate
|
|
@protocol ASCollectionDelegate <ASCommonCollectionViewDelegate, NSObject>
|
|
|
|
@optional
|
|
|
|
- (void)collectionView:(ASCollectionView *)collectionView willDisplayNodeForItemAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
/**
|
|
* Informs the delegate that the collection view did remove the provided node from the view hierarchy.
|
|
* This may be caused by the node scrolling out of view, or by deleting the item
|
|
* or its containing section with @c deleteItemsAtIndexPaths: or @c deleteSections: .
|
|
*
|
|
* @param collectionView The sender.
|
|
* @param node The node which was removed from the view hierarchy.
|
|
* @param indexPath The index path at which the node was located before it was removed.
|
|
*/
|
|
- (void)collectionView:(ASCollectionView *)collectionView didEndDisplayingNode:(ASCellNode *)node forItemAtIndexPath:(NSIndexPath *)indexPath;
|
|
|
|
/**
|
|
* Receive a message that the collectionView is near the end of its data set and more data should be fetched if
|
|
* necessary.
|
|
*
|
|
* @param collectionView The sender.
|
|
* @param context A context object that must be notified when the batch fetch is completed.
|
|
*
|
|
* @discussion You must eventually call -completeBatchFetching: with an argument of YES in order to receive future
|
|
* notifications to do batch fetches. This method is called on a background queue.
|
|
*
|
|
* UICollectionView currently only supports batch events for tail loads. If you require a head load, consider
|
|
* implementing a UIRefreshControl.
|
|
*/
|
|
- (void)collectionView:(ASCollectionView *)collectionView willBeginBatchFetchWithContext:(ASBatchContext *)context;
|
|
|
|
/**
|
|
* Tell the collectionView if batch fetching should begin.
|
|
*
|
|
* @param collectionView The sender.
|
|
*
|
|
* @discussion Use this method to conditionally fetch batches. Example use cases are: limiting the total number of
|
|
* objects that can be fetched or no network connection.
|
|
*
|
|
* If not implemented, the collectionView assumes that it should notify its asyncDelegate when batch fetching
|
|
* should occur.
|
|
*/
|
|
- (BOOL)shouldBatchFetchForCollectionView:(ASCollectionView *)collectionView;
|
|
|
|
/**
|
|
* Informs the delegate that the collection view did remove the node which was previously
|
|
* at the given index path from the view hierarchy.
|
|
*
|
|
* This method is deprecated. Use @c collectionView:didEndDisplayingNode:forItemAtIndexPath: instead.
|
|
*/
|
|
- (void)collectionView:(ASCollectionView *)collectionView didEndDisplayingNodeForItemAtIndexPath:(NSIndexPath *)indexPath ASDISPLAYNODE_DEPRECATED;
|
|
|
|
@end
|
|
|
|
/**
|
|
* Defines methods that let you coordinate with a `UICollectionViewFlowLayout` in combination with an `ASCollectionView`.
|
|
*/
|
|
@protocol ASCollectionViewDelegateFlowLayout <ASCollectionViewDelegate>
|
|
|
|
@optional
|
|
|
|
/**
|
|
* Passthrough support to UICollectionViewDelegateFlowLayout sectionInset behavior.
|
|
*
|
|
* @param collectionView The sender.
|
|
* @param collectionViewLayout The layout object requesting the information.
|
|
* @param section The index number of the section whose insets are needed.
|
|
*
|
|
* @discussion The same rules apply as the UICollectionView implementation, but this can also be used without a UICollectionViewFlowLayout.
|
|
* https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionViewDelegateFlowLayout_protocol/index.html#//apple_ref/occ/intfm/UICollectionViewDelegateFlowLayout/collectionView:layout:insetForSectionAtIndex:
|
|
*
|
|
*/
|
|
- (UIEdgeInsets)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
|
|
|
|
/**
|
|
* Asks the delegate for the size of the header in the specified section.
|
|
*/
|
|
- (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;
|
|
|
|
/**
|
|
* Asks the delegate for the size of the footer in the specified section.
|
|
*/
|
|
- (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;
|
|
|
|
@end
|
|
|
|
@interface ASCollectionView (Deprecated)
|
|
|
|
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout asyncDataFetching:(BOOL)asyncDataFetchingEnabled ASDISPLAYNODE_DEPRECATED;
|
|
|
|
@end
|
|
|
|
NS_ASSUME_NONNULL_END
|