Swiftgram/AsyncDisplayKit/Details/ASRangeController.h
Scott Goodson 21bebb9d29 [ASRangeController] Improvements to application state change and memory warning handling.
Introduces ASLayoutRangeModeVisibleOnly, allowing the preservation of decoded backing stores without any extra padding to
strictly minimize memory usage while supporting immediate re-display of content.  Set visible range controllers to this mode
upon app suspend / memory warning, while more aggressively clearing others to the ASLayoutRangeModeLowMemory mode.

By default, when the app is running and recieves a memory warning, we set the range mode for non-visible controllers to
ASLayoutRangeModeVisibleOnly.  This is because, unlike in the app suspend case where on app resume we can restore controllers
from LowMemory to VisibleOnly, the memory warning doesn't provide a good opportunity to do this.

A new +Beta API to control this behavior is called +setRangeModeForMemoryWarnings:, as some apps may prefer to use LowMemory
in the memory warning scenario.  For these apps, optimal user experience will require manually setting the range mode back
to some larger value as the user navigates the app, or they will encounter controllers that are temporarily blank and need
a moment to re-display their contents as they start to become visible.
2016-03-09 21:22:45 -08:00

197 lines
6.8 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 <Foundation/Foundation.h>
#import <AsyncDisplayKit/ASCellNode.h>
#import <AsyncDisplayKit/ASDataController.h>
#import <AsyncDisplayKit/ASLayoutController.h>
#import <AsyncDisplayKit/ASLayoutRangeType.h>
#define ASRangeControllerLoggingEnabled 0
NS_ASSUME_NONNULL_BEGIN
@protocol ASRangeControllerDataSource;
@protocol ASRangeControllerDelegate;
/**
* Working range controller.
*
* Used internally by ASTableView and ASCollectionView. It is paired with ASDataController.
* It is designed to support custom scrolling containers as well. Observes the visible range, maintains
* "working ranges" to trigger network calls and rendering, and is responsible for driving asynchronous layout of cells.
* This includes cancelling those asynchronous operations as cells fall outside of the working ranges.
*/
@interface ASRangeController : ASDealloc2MainObject <ASDataControllerDelegate>
{
id<ASLayoutController> _layoutController;
__weak id<ASRangeControllerDataSource> _dataSource;
__weak id<ASRangeControllerDelegate> _delegate;
}
/**
* Notify the range controller that the visible range has been updated.
* This is the primary input call that drives updating the working ranges, and triggering their actions.
*
* @param scrollDirection The current scroll direction of the scroll view.
*
* @see [ASRangeControllerDelegate rangeControllerVisibleNodeIndexPaths:]
*/
- (void)visibleNodeIndexPathsDidChangeWithScrollDirection:(ASScrollDirection)scrollDirection;
/**
* Add the sized node for `indexPath` as a subview of `contentView`.
*
* @param contentView UIView to add a (sized) node's view to.
*
* @param node The cell node to be added.
*/
- (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node;
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType;
- (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType;
// These methods call the corresponding method on each node, visiting each one that
// the range controller has set a non-default interface state on.
- (void)clearContents;
- (void)clearFetchedData;
/**
* An object that describes the layout behavior of the ranged component (table view, collection view, etc.)
*
* Used primarily for providing the current range of index paths and identifying when the
* range controller should invalidate its range.
*/
@property (nonatomic, strong) id<ASLayoutController> layoutController;
/**
* The underlying data source for the range controller
*/
@property (nonatomic, weak) id<ASRangeControllerDataSource> dataSource;
/**
* Delegate for handling range controller events. Must not be nil.
*/
@property (nonatomic, weak) id<ASRangeControllerDelegate> delegate;
@end
/**
* Data source for ASRangeController.
*
* Allows the range controller to perform external queries on the range.
* Ex. range nodes, visible index paths, and viewport size.
*/
@protocol ASRangeControllerDataSource <NSObject>
/**
* @param rangeController Sender.
*
* @returns an array of index paths corresponding to the nodes currently visible onscreen (i.e., the visible range).
*/
- (NSArray<NSIndexPath *> *)visibleNodeIndexPathsForRangeController:(ASRangeController *)rangeController;
/**
* @param rangeController Sender.
*
* @returns the receiver's viewport size (i.e., the screen space occupied by the visible range).
*/
- (CGSize)viewportSizeForRangeController:(ASRangeController *)rangeController;
/**
* @param rangeController Sender.
*
* @returns the ASInterfaceState of the node that this controller is powering. This allows nested range controllers
* to collaborate with one another, as an outer controller may set bits in .interfaceState such as Visible.
* If this controller is an orthogonally scrolling element, it waits until it is visible to preload outside the viewport.
*/
- (ASInterfaceState)interfaceStateForRangeController:(ASRangeController *)rangeController;
- (NSArray *)rangeController:(ASRangeController *)rangeController nodesAtIndexPaths:(NSArray *)indexPaths;
- (ASDisplayNode *)rangeController:(ASRangeController *)rangeController nodeAtIndexPath:(NSIndexPath *)indexPath;
- (NSArray<NSArray <ASCellNode *> *> *)completedNodes;
@end
/**
* Delegate for ASRangeController.
*/
@protocol ASRangeControllerDelegate <NSObject>
/**
* Begin updates.
*
* @param rangeController Sender.
*/
- (void)didBeginUpdatesInRangeController:(ASRangeController *)rangeController;
/**
* End updates.
*
* @param rangeController Sender.
* @param animated NO if all animations are disabled. YES otherwise.
* @param completion Completion block.
*/
- (void)rangeController:(ASRangeController * )rangeController didEndUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion;
/**
* Called for nodes insertion.
*
* @param rangeController Sender.
*
* @param nodes Inserted nodes.
*
* @param indexPaths Index path of inserted nodes.
*
* @param animationOptions Animation options. See ASDataControllerAnimationOptions.
*/
- (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray<ASCellNode *> *)nodes atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions;
/**
* Called for nodes deletion.
*
* @param rangeController Sender.
*
* @param nodes Deleted nodes.
*
* @param indexPaths Index path of deleted nodes.
*
* @param animationOptions Animation options. See ASDataControllerAnimationOptions.
*/
- (void)rangeController:(ASRangeController *)rangeController didDeleteNodes:(NSArray<ASCellNode *> *)nodes atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions;
/**
* Called for section insertion.
*
* @param rangeController Sender.
*
* @param indexSet Index set of inserted sections.
*
* @param animationOptions Animation options. See ASDataControllerAnimationOptions.
*/
- (void)rangeController:(ASRangeController *)rangeController didInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions;
/**
* Called for section deletion.
*
* @param rangeController Sender.
*
* @param indexSet Index set of deleted sections.
*
* @param animationOptions Animation options. See ASDataControllerAnimationOptions.
*/
- (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions;
@end
NS_ASSUME_NONNULL_END