mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-16 19:30:29 +00:00
Stub out ASCollectionDataController subclass
This commit is contained in:
parent
e492770aed
commit
e9eadac4ae
@ -11,7 +11,7 @@
|
|||||||
#import "ASAssert.h"
|
#import "ASAssert.h"
|
||||||
#import "ASCollectionViewLayoutController.h"
|
#import "ASCollectionViewLayoutController.h"
|
||||||
#import "ASRangeController.h"
|
#import "ASRangeController.h"
|
||||||
#import "ASDataController.h"
|
#import "ASCollectionDataController.h"
|
||||||
#import "ASDisplayNodeInternal.h"
|
#import "ASDisplayNodeInternal.h"
|
||||||
#import "ASBatchFetching.h"
|
#import "ASBatchFetching.h"
|
||||||
#import "UICollectionViewLayout+ASConvenience.h"
|
#import "UICollectionViewLayout+ASConvenience.h"
|
||||||
@ -37,9 +37,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
// handled by ASCollectionView node<->cell machinery
|
// handled by ASCollectionView node<->cell machinery
|
||||||
sel == @selector(collectionView:cellForItemAtIndexPath:) ||
|
sel == @selector(collectionView:cellForItemAtIndexPath:) ||
|
||||||
sel == @selector(collectionView:layout:sizeForItemAtIndexPath:) ||
|
sel == @selector(collectionView:layout:sizeForItemAtIndexPath:) ||
|
||||||
|
sel == @selector(collectionView:viewForSupplementaryElementOfKind:atIndexPath:) ||
|
||||||
// TODO: Supplementary views are currently not supported. An assertion is triggered if the _asyncDataSource implements this method.
|
|
||||||
// sel == @selector(collectionView:viewForSupplementaryElementOfKind:atIndexPath:) ||
|
|
||||||
|
|
||||||
// handled by ASRangeController
|
// handled by ASRangeController
|
||||||
sel == @selector(numberOfSectionsInCollectionView:) ||
|
sel == @selector(numberOfSectionsInCollectionView:) ||
|
||||||
@ -136,7 +134,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
_ASCollectionViewProxy *_proxyDataSource;
|
_ASCollectionViewProxy *_proxyDataSource;
|
||||||
_ASCollectionViewProxy *_proxyDelegate;
|
_ASCollectionViewProxy *_proxyDelegate;
|
||||||
|
|
||||||
ASDataController *_dataController;
|
ASCollectionDataController *_dataController;
|
||||||
ASRangeController *_rangeController;
|
ASRangeController *_rangeController;
|
||||||
ASCollectionViewLayoutController *_layoutController;
|
ASCollectionViewLayoutController *_layoutController;
|
||||||
|
|
||||||
@ -201,7 +199,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
_rangeController.delegate = self;
|
_rangeController.delegate = self;
|
||||||
_rangeController.layoutController = _layoutController;
|
_rangeController.layoutController = _layoutController;
|
||||||
|
|
||||||
_dataController = [[ASDataController alloc] initWithAsyncDataFetching:asyncDataFetchingEnabled];
|
_dataController = [[ASCollectionDataController alloc] initWithAsyncDataFetching:asyncDataFetchingEnabled];
|
||||||
_dataController.delegate = _rangeController;
|
_dataController.delegate = _rangeController;
|
||||||
_dataController.dataSource = self;
|
_dataController.dataSource = self;
|
||||||
|
|
||||||
@ -381,8 +379,8 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
|
|
||||||
- (void)registerSupplementaryViewOfKind:(NSString *)elementKind
|
- (void)registerSupplementaryViewOfKind:(NSString *)elementKind
|
||||||
{
|
{
|
||||||
NSString *identifier = [NSString stringWithFormat:@"_ASCollectionSupplementaryView_%@", elementKind];
|
[self registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:elementKind
|
||||||
[self registerClass:[UIView class] forSupplementaryViewOfKind:elementKind withReuseIdentifier:identifier];
|
withReuseIdentifier:[self __reuseIdentifierForKind:elementKind]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)insertSections:(NSIndexSet *)sections
|
- (void)insertSections:(NSIndexSet *)sections
|
||||||
@ -433,6 +431,16 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
[_dataController moveRowAtIndexPath:indexPath toIndexPath:newIndexPath withAnimationOptions:kASCollectionViewAnimationNone];
|
[_dataController moveRowAtIndexPath:indexPath toIndexPath:newIndexPath withAnimationOptions:kASCollectionViewAnimationNone];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (ASCellNode *)nodeForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
return [_dataController nodeAtIndexPath:indexPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString *)__reuseIdentifierForKind:(NSString *)kind
|
||||||
|
{
|
||||||
|
return [NSString stringWithFormat:@"_ASCollectionSupplementaryView_%@", kind];
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
#pragma mark Intercepted selectors.
|
#pragma mark Intercepted selectors.
|
||||||
|
|
||||||
@ -443,7 +451,8 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
_ASCollectionViewCell *cell = [self dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
|
_ASCollectionViewCell *cell = [self dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
|
||||||
|
|
||||||
ASCellNode *node = [_dataController nodeAtIndexPath:indexPath];
|
ASCellNode *node = [_dataController nodeAtIndexPath:indexPath];
|
||||||
[_rangeController configureContentView:cell.contentView forCellNode:node];
|
|
||||||
|
[_rangeController configureContentView:cell.contentView forNode:node];
|
||||||
|
|
||||||
cell.node = node;
|
cell.node = node;
|
||||||
|
|
||||||
@ -455,6 +464,15 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
return [[_dataController nodeAtIndexPath:indexPath] calculatedSize];
|
return [[_dataController nodeAtIndexPath:indexPath] calculatedSize];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
NSString *identifier = [self __reuseIdentifierForKind:kind];
|
||||||
|
UICollectionReusableView *view = [self dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:identifier forIndexPath:indexPath];
|
||||||
|
ASDisplayNode *node = [_dataController supplementaryNodeOfKind:kind atIndexPath:indexPath];
|
||||||
|
[_rangeController configureContentView:view forNode:node];
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
|
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
|
||||||
{
|
{
|
||||||
_superIsPendingDataLoad = NO;
|
_superIsPendingDataLoad = NO;
|
||||||
@ -613,6 +631,11 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (ASDisplayNode *)dataController:(ASDataController *)dataController supplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
return [_asyncDataSource collectionView:self nodeForSupplementaryElementOfKind:kind atIndexPath:indexPath];
|
||||||
|
}
|
||||||
|
|
||||||
- (ASSizeRange)dataController:(ASDataController *)dataController constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
- (ASSizeRange)dataController:(ASDataController *)dataController constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||||
{
|
{
|
||||||
ASSizeRange constrainedSize;
|
ASSizeRange constrainedSize;
|
||||||
@ -659,7 +682,7 @@ static BOOL _isInterceptedSelector(SEL sel)
|
|||||||
return [_asyncDataSource collectionView:self numberOfItemsInSection:section];
|
return [_asyncDataSource collectionView:self numberOfItemsInSection:section];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)dataControllerNumberOfSections:(ASDataController *)dataController {
|
- (NSUInteger)numberOfSectionsInDataController:(ASDataController *)dataController {
|
||||||
if ([_asyncDataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)]) {
|
if ([_asyncDataSource respondsToSelector:@selector(numberOfSectionsInCollectionView:)]) {
|
||||||
return [_asyncDataSource numberOfSectionsInCollectionView:self];
|
return [_asyncDataSource numberOfSectionsInCollectionView:self];
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -530,7 +530,7 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ASCellNode *node = [_dataController nodeAtIndexPath:indexPath];
|
ASCellNode *node = [_dataController nodeAtIndexPath:indexPath];
|
||||||
[_rangeController configureContentView:cell.contentView forCellNode:node];
|
[_rangeController configureContentView:cell.contentView forNode:node];
|
||||||
|
|
||||||
cell.node = node;
|
cell.node = node;
|
||||||
cell.backgroundColor = node.backgroundColor;
|
cell.backgroundColor = node.backgroundColor;
|
||||||
@ -859,7 +859,7 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) {
|
|||||||
return [_asyncDataSource tableView:self numberOfRowsInSection:section];
|
return [_asyncDataSource tableView:self numberOfRowsInSection:section];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSUInteger)dataControllerNumberOfSections:(ASDataController *)dataController
|
- (NSUInteger)numberOfSectionsInDataController:(ASDataController *)dataController
|
||||||
{
|
{
|
||||||
if ([_asyncDataSource respondsToSelector:@selector(numberOfSectionsInTableView:)]) {
|
if ([_asyncDataSource respondsToSelector:@selector(numberOfSectionsInTableView:)]) {
|
||||||
return [_asyncDataSource numberOfSectionsInTableView:self];
|
return [_asyncDataSource numberOfSectionsInTableView:self];
|
||||||
|
|||||||
26
AsyncDisplayKit/Details/ASCollectionDataController.h
Normal file
26
AsyncDisplayKit/Details/ASCollectionDataController.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// ASCollectionDataController.h
|
||||||
|
// Pods
|
||||||
|
//
|
||||||
|
// Created by Levi McCallum on 9/22/15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <AsyncDisplayKit/ASDataController.h>
|
||||||
|
|
||||||
|
@class ASDisplayNode, ASCollectionDataController;
|
||||||
|
@protocol ASDataControllerSource;
|
||||||
|
|
||||||
|
@protocol ASCollectionDataControllerSource <ASDataControllerSource>
|
||||||
|
|
||||||
|
- (ASDisplayNode *)dataController:(ASDataController *)dataController supplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
|
||||||
|
|
||||||
|
- (NSArray *)supplementaryKindsInDataController:(ASCollectionDataController *)dataController;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface ASCollectionDataController : ASDataController
|
||||||
|
|
||||||
|
- (ASDisplayNode *)supplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
|
||||||
|
|
||||||
|
@end
|
||||||
72
AsyncDisplayKit/Details/ASCollectionDataController.m
Normal file
72
AsyncDisplayKit/Details/ASCollectionDataController.m
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
//
|
||||||
|
// ASCollectionDataController.m
|
||||||
|
// Pods
|
||||||
|
//
|
||||||
|
// Created by Levi McCallum on 9/22/15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ASCollectionDataController.h"
|
||||||
|
|
||||||
|
#import "ASAssert.h"
|
||||||
|
|
||||||
|
@interface ASDataController (Subclasses)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queues the given operation until an `endUpdates` synchronize update is completed.
|
||||||
|
*
|
||||||
|
* If this method is called outside of a begin/endUpdates batch update, the block is
|
||||||
|
* executed immediately.
|
||||||
|
*/
|
||||||
|
- (void)performEditCommandWithBlock:(void (^)(void))block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Safely locks access to the data source and executes the given block, unlocking once complete.
|
||||||
|
*
|
||||||
|
* When `asyncDataFetching` is enabled, the block is executed on a background thread.
|
||||||
|
*/
|
||||||
|
- (void)accessDataSourceWithBlock:(dispatch_block_t)block;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ASCollectionDataController {
|
||||||
|
NSMutableDictionary *_completedSupplementaryNodes;
|
||||||
|
NSMutableDictionary *_editingSupplementaryNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)initialSupplementaryLoading
|
||||||
|
{
|
||||||
|
[self performEditCommandWithBlock:^{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
[self accessDataSourceWithBlock:^{
|
||||||
|
NSArray *elementKinds = [self.collectionDataSource supplementaryKindsInDataController:self];
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (ASDisplayNode *)supplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
return _completedSupplementaryNodes[kind][indexPath.section][indexPath.item];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id<ASCollectionDataControllerSource>)collectionDataSource
|
||||||
|
{
|
||||||
|
return (id<ASCollectionDataControllerSource>)self.dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Internal Data Querying
|
||||||
|
|
||||||
|
- (void)_insertNodes:(NSArray *)nodes ofKind:(NSString *)kind atIndexPaths:(NSArray *)indexPaths
|
||||||
|
{
|
||||||
|
if (indexPaths.count == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_deleteNodesOfKind:(NSString *)kind atIndexPaths:(NSArray *)indexPaths
|
||||||
|
{
|
||||||
|
if (indexPaths.count == 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@ -40,7 +40,7 @@ typedef NSUInteger ASDataControllerAnimationOptions;
|
|||||||
/**
|
/**
|
||||||
Fetch the number of sections.
|
Fetch the number of sections.
|
||||||
*/
|
*/
|
||||||
- (NSUInteger)dataControllerNumberOfSections:(ASDataController *)dataController;
|
- (NSUInteger)numberOfSectionsInDataController:(ASDataController *)dataController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Lock the data source for data fetching.
|
Lock the data source for data fetching.
|
||||||
|
|||||||
@ -239,7 +239,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
|||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
[self accessDataSourceWithBlock:^{
|
[self accessDataSourceWithBlock:^{
|
||||||
NSMutableArray *indexPaths = [NSMutableArray array];
|
NSMutableArray *indexPaths = [NSMutableArray array];
|
||||||
NSUInteger sectionNum = [_dataSource dataControllerNumberOfSections:self];
|
NSUInteger sectionNum = [_dataSource numberOfSectionsInDataController:self];
|
||||||
|
|
||||||
// insert sections
|
// insert sections
|
||||||
[self insertSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionNum)] withAnimationOptions:0];
|
[self insertSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, sectionNum)] withAnimationOptions:0];
|
||||||
@ -266,7 +266,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
|||||||
[_editingTransactionQueue waitUntilAllOperationsAreFinished];
|
[_editingTransactionQueue waitUntilAllOperationsAreFinished];
|
||||||
|
|
||||||
[self accessDataSourceWithBlock:^{
|
[self accessDataSourceWithBlock:^{
|
||||||
NSUInteger sectionCount = [_dataSource dataControllerNumberOfSections:self];
|
NSUInteger sectionCount = [_dataSource numberOfSectionsInDataController:self];
|
||||||
NSMutableArray *updatedNodes = [NSMutableArray array];
|
NSMutableArray *updatedNodes = [NSMutableArray array];
|
||||||
NSMutableArray *updatedIndexPaths = [NSMutableArray array];
|
NSMutableArray *updatedIndexPaths = [NSMutableArray array];
|
||||||
[self _populateFromEntireDataSourceWithMutableNodes:updatedNodes mutableIndexPaths:updatedIndexPaths];
|
[self _populateFromEntireDataSourceWithMutableNodes:updatedNodes mutableIndexPaths:updatedIndexPaths];
|
||||||
@ -335,7 +335,7 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
|||||||
|
|
||||||
- (void)_populateFromEntireDataSourceWithMutableNodes:(NSMutableArray *)nodes mutableIndexPaths:(NSMutableArray *)indexPaths
|
- (void)_populateFromEntireDataSourceWithMutableNodes:(NSMutableArray *)nodes mutableIndexPaths:(NSMutableArray *)indexPaths
|
||||||
{
|
{
|
||||||
NSUInteger sectionNum = [_dataSource dataControllerNumberOfSections:self];
|
NSUInteger sectionNum = [_dataSource numberOfSectionsInDataController:self];
|
||||||
for (NSUInteger i = 0; i < sectionNum; i++) {
|
for (NSUInteger i = 0; i < sectionNum; i++) {
|
||||||
NSIndexPath *sectionIndexPath = [[NSIndexPath alloc] initWithIndex:i];
|
NSIndexPath *sectionIndexPath = [[NSIndexPath alloc] initWithIndex:i];
|
||||||
|
|
||||||
|
|||||||
@ -41,9 +41,9 @@
|
|||||||
*
|
*
|
||||||
* @param contentView UIView to add a (sized) node's view to.
|
* @param contentView UIView to add a (sized) node's view to.
|
||||||
*
|
*
|
||||||
* @param node The ASCellNode to be added.
|
* @param node The node to be added. Often an ASCellNode.
|
||||||
*/
|
*/
|
||||||
- (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)node;
|
- (void)configureContentView:(UIView *)contentView forNode:(ASDisplayNode *)node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delegate and ultimate data source. Must not be nil.
|
* Delegate and ultimate data source. Must not be nil.
|
||||||
|
|||||||
@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
#pragma mark - View manipulation
|
#pragma mark - View manipulation
|
||||||
|
|
||||||
- (void)moveNode:(ASCellNode *)node toView:(UIView *)view
|
- (void)moveNode:(ASDisplayNode *)node toView:(UIView *)view
|
||||||
{
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
ASDisplayNodeAssert(node, @"Cannot move a nil node to a view");
|
ASDisplayNodeAssert(node, @"Cannot move a nil node to a view");
|
||||||
@ -158,7 +158,7 @@
|
|||||||
return rangeType == ASLayoutRangeTypeRender;
|
return rangeType == ASLayoutRangeTypeRender;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)configureContentView:(UIView *)contentView forCellNode:(ASCellNode *)cellNode
|
- (void)configureContentView:(UIView *)contentView forNode:(ASDisplayNode *)cellNode
|
||||||
{
|
{
|
||||||
if (cellNode.view.superview == contentView) {
|
if (cellNode.view.superview == contentView) {
|
||||||
// this content view is already correctly configured
|
// this content view is already correctly configured
|
||||||
|
|||||||
@ -64,7 +64,7 @@
|
|||||||
// This happens if the UITableViewCell is reused after scrolling offscreen. Because the node has already been given the opportunity to display, we do not
|
// This happens if the UITableViewCell is reused after scrolling offscreen. Because the node has already been given the opportunity to display, we do not
|
||||||
// proactively re-host it within the workingWindow (improving efficiency). Some time later, it may fall outside the working range, in which case calling
|
// proactively re-host it within the workingWindow (improving efficiency). Some time later, it may fall outside the working range, in which case calling
|
||||||
// -recursivelyClearContents is critical. If the user scrolls back and it is re-hosted in a UITableViewCell, the content will still exist as it is not cleared
|
// -recursivelyClearContents is critical. If the user scrolls back and it is re-hosted in a UITableViewCell, the content will still exist as it is not cleared
|
||||||
// by simply being removed from the cell. The code that usually triggers this condition is the -removeFromSuperview in -[ASRangeController configureContentView:forCellNode:].
|
// by simply being removed from the cell. The code that usually triggers this condition is the -removeFromSuperview in -[ASRangeController configureContentView:forNode:].
|
||||||
// Condition #4 is suboptimal in some cases, as it is conceivable that memory warnings could trigger clearing content that is inside the working range. However, enforcing the
|
// Condition #4 is suboptimal in some cases, as it is conceivable that memory warnings could trigger clearing content that is inside the working range. However, enforcing the
|
||||||
// preservation of this content could result in the app being killed, which is not likely preferable over briefly seeing placeholders in the event the user scrolls backwards.
|
// preservation of this content could result in the app being killed, which is not likely preferable over briefly seeing placeholders in the event the user scrolls backwards.
|
||||||
// Nonetheless, future changes to the implementation will likely eliminate this behavior to simplify debugging and extensibility of working range functionality.
|
// Nonetheless, future changes to the implementation will likely eliminate this behavior to simplify debugging and extensibility of working range functionality.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user