mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 14:45:21 +00:00
[ASCellNode] Added indexPath property. (#2468)
* [ASCellNode] Added indexPath property. * [ASCellNode] Cached the type of scrollView we're using in the node, and placed that logic in setScrollView. * [ASCellNode] Removed table and collection view from indexPath, since they return the index paths from the view-space. * Changed the logic for getting indexPath so that it works even when the cell is not displayed. * [VerticalWithinHorizontalScrolling] Explicitally synthesized indexPath property.
This commit is contained in:
@@ -63,6 +63,8 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
|
|
||||||
@property (nonatomic, copy, nullable) NSIndexPath *cachedIndexPath;
|
@property (nonatomic, copy, nullable) NSIndexPath *cachedIndexPath;
|
||||||
|
|
||||||
|
@property (weak, nonatomic, nullable) ASDisplayNode *owningNode;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
|||||||
@@ -108,6 +108,20 @@ typedef NS_ENUM(NSUInteger, ASCellNodeVisibilityEvent) {
|
|||||||
*/
|
*/
|
||||||
@property (nonatomic, assign, getter=isHighlighted) BOOL highlighted;
|
@property (nonatomic, assign, getter=isHighlighted) BOOL highlighted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current index path of this cell node, or @c nil if this node is
|
||||||
|
* not a valid item inside a table node or collection node.
|
||||||
|
*
|
||||||
|
* @note This property must be accessed on the main thread.
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, nullable) NSIndexPath *indexPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The owning node (ASCollectionNode/ASTableNode) of this cell node, or @c nil if this node is
|
||||||
|
* not a valid item inside a table node or collection node or if those nodes are nil.
|
||||||
|
*/
|
||||||
|
@property (weak, nonatomic, readonly, nullable) ASDisplayNode *owningNode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding
|
* ASCellNode must forward touch events in order for UITableView and UICollectionView tap handling to work. Overriding
|
||||||
* these methods (e.g. for highlighting) requires the super method be called.
|
* these methods (e.g. for highlighting) requires the super method be called.
|
||||||
|
|||||||
@@ -36,6 +36,12 @@
|
|||||||
ASDisplayNode *_viewControllerNode;
|
ASDisplayNode *_viewControllerNode;
|
||||||
UIViewController *_viewController;
|
UIViewController *_viewController;
|
||||||
BOOL _suspendInteractionDelegate;
|
BOOL _suspendInteractionDelegate;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
unsigned int isTableNode:1;
|
||||||
|
unsigned int isCollectionNode:1;
|
||||||
|
} _owningNodeType;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -186,6 +192,19 @@ static NSMutableSet *__cellClassesForVisibilityNotifications = nil; // See +init
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setOwningNode:(ASDisplayNode *)owningNode
|
||||||
|
{
|
||||||
|
_owningNode = owningNode;
|
||||||
|
|
||||||
|
memset(&_owningNodeType, 0, sizeof(_owningNodeType));
|
||||||
|
|
||||||
|
if ([owningNode isKindOfClass:[ASTableNode class]]) {
|
||||||
|
_owningNodeType.isTableNode = 1;
|
||||||
|
} else if ([owningNode isKindOfClass:[ASCollectionNode class]]) {
|
||||||
|
_owningNodeType.isCollectionNode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)__setSelectedFromUIKit:(BOOL)selected;
|
- (void)__setSelectedFromUIKit:(BOOL)selected;
|
||||||
{
|
{
|
||||||
if (selected != _selected) {
|
if (selected != _selected) {
|
||||||
@@ -204,6 +223,19 @@ static NSMutableSet *__cellClassesForVisibilityNotifications = nil; // See +init
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSIndexPath *)indexPath
|
||||||
|
{
|
||||||
|
ASDisplayNodeAssertMainThread();
|
||||||
|
|
||||||
|
if (_owningNodeType.isTableNode) {
|
||||||
|
return [(ASTableNode *)self.owningNode indexPathForNode:self];
|
||||||
|
} else if (_owningNodeType.isCollectionNode) {
|
||||||
|
return [(ASCollectionNode *)self.owningNode indexPathForNode:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
#pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
|
#pragma clang diagnostic ignored "-Wobjc-missing-super-calls"
|
||||||
|
|
||||||
|
|||||||
@@ -233,15 +233,14 @@
|
|||||||
|
|
||||||
- (void)_populateSupplementaryNodesOfKind:(NSString *)kind withSections:(NSIndexSet *)sections mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts
|
- (void)_populateSupplementaryNodesOfKind:(NSString *)kind withSections:(NSIndexSet *)sections mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts
|
||||||
{
|
{
|
||||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
|
||||||
|
|
||||||
[sections enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
[sections enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||||
for (NSUInteger sec = range.location; sec < NSMaxRange(range); sec++) {
|
for (NSUInteger sec = range.location; sec < NSMaxRange(range); sec++) {
|
||||||
NSUInteger itemCount = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:sec];
|
NSUInteger itemCount = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:sec];
|
||||||
for (NSUInteger i = 0; i < itemCount; i++) {
|
for (NSUInteger i = 0; i < itemCount; i++) {
|
||||||
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:sec];
|
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:sec];
|
||||||
[self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environmentTraitCollection:environmentTraitCollection];
|
[self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environment:environment];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
@@ -249,8 +248,7 @@
|
|||||||
|
|
||||||
- (void)_populateSupplementaryNodesOfKind:(NSString *)kind atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts
|
- (void)_populateSupplementaryNodesOfKind:(NSString *)kind atIndexPaths:(NSArray<NSIndexPath *> *)indexPaths mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts
|
||||||
{
|
{
|
||||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
|
||||||
|
|
||||||
NSMutableIndexSet *sections = [NSMutableIndexSet indexSet];
|
NSMutableIndexSet *sections = [NSMutableIndexSet indexSet];
|
||||||
for (NSIndexPath *indexPath in indexPaths) {
|
for (NSIndexPath *indexPath in indexPaths) {
|
||||||
@@ -262,13 +260,13 @@
|
|||||||
NSUInteger itemCount = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:sec];
|
NSUInteger itemCount = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:sec];
|
||||||
for (NSUInteger i = 0; i < itemCount; i++) {
|
for (NSUInteger i = 0; i < itemCount; i++) {
|
||||||
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:sec];
|
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:sec];
|
||||||
[self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environmentTraitCollection:environmentTraitCollection];
|
[self _populateSupplementaryNodeOfKind:kind atIndexPath:indexPath mutableContexts:contexts environment:environment];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_populateSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts environmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection
|
- (void)_populateSupplementaryNodeOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts environment:(id<ASEnvironment>)environment
|
||||||
{
|
{
|
||||||
ASCellNodeBlock supplementaryCellBlock;
|
ASCellNodeBlock supplementaryCellBlock;
|
||||||
if (_dataSourceImplementsSupplementaryNodeBlockOfKindAtIndexPath) {
|
if (_dataSourceImplementsSupplementaryNodeBlockOfKindAtIndexPath) {
|
||||||
@@ -283,7 +281,7 @@
|
|||||||
indexPath:indexPath
|
indexPath:indexPath
|
||||||
supplementaryElementKind:kind
|
supplementaryElementKind:kind
|
||||||
constrainedSize:constrainedSize
|
constrainedSize:constrainedSize
|
||||||
environmentTraitCollection:environmentTraitCollection];
|
environment:environment];
|
||||||
[contexts addObject:context];
|
[contexts addObject:context];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -476,8 +476,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
|||||||
{
|
{
|
||||||
ASDisplayNodeAssertMainThread();
|
ASDisplayNodeAssertMainThread();
|
||||||
|
|
||||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
|
||||||
|
|
||||||
std::vector<NSInteger> counts = [self itemCountsFromDataSource];
|
std::vector<NSInteger> counts = [self itemCountsFromDataSource];
|
||||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
||||||
@@ -493,7 +492,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
|||||||
indexPath:indexPath
|
indexPath:indexPath
|
||||||
supplementaryElementKind:nil
|
supplementaryElementKind:nil
|
||||||
constrainedSize:constrainedSize
|
constrainedSize:constrainedSize
|
||||||
environmentTraitCollection:environmentTraitCollection]];
|
environment:environment]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
@@ -743,8 +742,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
|||||||
NSArray *sortedIndexPaths = [indexPaths sortedArrayUsingSelector:@selector(compare:)];
|
NSArray *sortedIndexPaths = [indexPaths sortedArrayUsingSelector:@selector(compare:)];
|
||||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [[NSMutableArray alloc] initWithCapacity:indexPaths.count];
|
NSMutableArray<ASIndexedNodeContext *> *contexts = [[NSMutableArray alloc] initWithCapacity:indexPaths.count];
|
||||||
|
|
||||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
|
||||||
|
|
||||||
for (NSIndexPath *indexPath in sortedIndexPaths) {
|
for (NSIndexPath *indexPath in sortedIndexPaths) {
|
||||||
ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath];
|
ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath];
|
||||||
@@ -753,7 +751,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
|||||||
indexPath:indexPath
|
indexPath:indexPath
|
||||||
supplementaryElementKind:nil
|
supplementaryElementKind:nil
|
||||||
constrainedSize:constrainedSize
|
constrainedSize:constrainedSize
|
||||||
environmentTraitCollection:environmentTraitCollection]];
|
environment:environment]];
|
||||||
}
|
}
|
||||||
|
|
||||||
ASInsertElementsIntoMultidimensionalArrayAtIndexPaths(_nodeContexts[ASDataControllerRowNodeKind], sortedIndexPaths, contexts);
|
ASInsertElementsIntoMultidimensionalArrayAtIndexPaths(_nodeContexts[ASDataControllerRowNodeKind], sortedIndexPaths, contexts);
|
||||||
|
|||||||
@@ -24,13 +24,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
@property (nonatomic, readonly, strong) NSIndexPath *indexPath;
|
@property (nonatomic, readonly, strong) NSIndexPath *indexPath;
|
||||||
@property (nonatomic, readonly, copy, nullable) NSString *supplementaryElementKind;
|
@property (nonatomic, readonly, copy, nullable) NSString *supplementaryElementKind;
|
||||||
@property (nonatomic, readonly, assign) ASSizeRange constrainedSize;
|
@property (nonatomic, readonly, assign) ASSizeRange constrainedSize;
|
||||||
|
@property (weak, nonatomic) id<ASEnvironment> environment;
|
||||||
@property (nonatomic, readonly, assign) ASEnvironmentTraitCollection environmentTraitCollection;
|
@property (nonatomic, readonly, assign) ASEnvironmentTraitCollection environmentTraitCollection;
|
||||||
|
|
||||||
- (instancetype)initWithNodeBlock:(ASCellNodeBlock)nodeBlock
|
- (instancetype)initWithNodeBlock:(ASCellNodeBlock)nodeBlock
|
||||||
indexPath:(NSIndexPath *)indexPath
|
indexPath:(NSIndexPath *)indexPath
|
||||||
supplementaryElementKind:(nullable NSString *)supplementaryElementKind
|
supplementaryElementKind:(nullable NSString *)supplementaryElementKind
|
||||||
constrainedSize:(ASSizeRange)constrainedSize
|
constrainedSize:(ASSizeRange)constrainedSize
|
||||||
environmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection;
|
environment:(id<ASEnvironment>)environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The node, running the node block if necessary. The node block will be discarded
|
* @return The node, running the node block if necessary. The node block will be discarded
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
indexPath:(NSIndexPath *)indexPath
|
indexPath:(NSIndexPath *)indexPath
|
||||||
supplementaryElementKind:(nullable NSString *)supplementaryElementKind
|
supplementaryElementKind:(nullable NSString *)supplementaryElementKind
|
||||||
constrainedSize:(ASSizeRange)constrainedSize
|
constrainedSize:(ASSizeRange)constrainedSize
|
||||||
environmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection
|
environment:(id<ASEnvironment>)environment
|
||||||
{
|
{
|
||||||
NSAssert(nodeBlock != nil && indexPath != nil, @"Node block and index path must not be nil");
|
NSAssert(nodeBlock != nil && indexPath != nil, @"Node block and index path must not be nil");
|
||||||
self = [super init];
|
self = [super init];
|
||||||
@@ -40,7 +40,8 @@
|
|||||||
_indexPath = indexPath;
|
_indexPath = indexPath;
|
||||||
_supplementaryElementKind = [supplementaryElementKind copy];
|
_supplementaryElementKind = [supplementaryElementKind copy];
|
||||||
_constrainedSize = constrainedSize;
|
_constrainedSize = constrainedSize;
|
||||||
_environmentTraitCollection = environmentTraitCollection;
|
_environment = environment;
|
||||||
|
_environmentTraitCollection = environment.environmentTraitCollection;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -57,6 +58,7 @@
|
|||||||
}
|
}
|
||||||
node.cachedIndexPath = _indexPath;
|
node.cachedIndexPath = _indexPath;
|
||||||
node.supplementaryElementKind = _supplementaryElementKind;
|
node.supplementaryElementKind = _supplementaryElementKind;
|
||||||
|
node.owningNode = (ASDisplayNode *)_environment;
|
||||||
ASEnvironmentStatePropagateDown(node, _environmentTraitCollection);
|
ASEnvironmentStatePropagateDown(node, _environmentTraitCollection);
|
||||||
_node = node;
|
_node = node;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -504,6 +504,45 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)testCellNodeIndexPathConsistency
|
||||||
|
{
|
||||||
|
updateValidationTestPrologue
|
||||||
|
|
||||||
|
// Test with a visible cell
|
||||||
|
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:2 inSection:0];
|
||||||
|
ASCellNode *cell = [cn nodeForItemAtIndexPath:indexPath];
|
||||||
|
|
||||||
|
// Check if cell's indexPath corresponds to the indexPath being tested
|
||||||
|
XCTAssertTrue(cell.indexPath.section == indexPath.section && cell.indexPath.item == indexPath.item, @"Expected the cell's indexPath to be the same as the indexPath being tested.");
|
||||||
|
|
||||||
|
// Remove an item prior to the cell's indexPath from the same section and check for indexPath consistency
|
||||||
|
--del->_itemCounts[indexPath.section];
|
||||||
|
[cn deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:indexPath.section]]];
|
||||||
|
XCTAssertTrue(cell.indexPath.section == indexPath.section && cell.indexPath.item == (indexPath.item - 1), @"Expected the cell's indexPath to be updated once a cell with a lower index is deleted.");
|
||||||
|
|
||||||
|
// Remove the section that includes the indexPath and check if the cell's indexPath is now nil
|
||||||
|
del->_itemCounts.erase(del->_itemCounts.begin());
|
||||||
|
[cn deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section]];
|
||||||
|
XCTAssertNil(cell.indexPath, @"Expected the cell's indexPath to be nil once the section that contains the node is deleted.");
|
||||||
|
|
||||||
|
// Run the same tests but with a non-displayed cell
|
||||||
|
indexPath = [NSIndexPath indexPathForItem:2 inSection:(del->_itemCounts.size() - 1)];
|
||||||
|
cell = [cn nodeForItemAtIndexPath:indexPath];
|
||||||
|
|
||||||
|
// Check if cell's indexPath corresponds to the indexPath being tested
|
||||||
|
XCTAssertTrue(cell.indexPath.section == indexPath.section && cell.indexPath.item == indexPath.item, @"Expected the cell's indexPath to be the same as the indexPath in question.");
|
||||||
|
|
||||||
|
// Remove an item prior to the cell's indexPath from the same section and check for indexPath consistency
|
||||||
|
--del->_itemCounts[indexPath.section];
|
||||||
|
[cn deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:indexPath.section]]];
|
||||||
|
XCTAssertTrue(cell.indexPath.section == indexPath.section && cell.indexPath.item == (indexPath.item - 1), @"Expected the cell's indexPath to be updated once a cell with a lower index is deleted.");
|
||||||
|
|
||||||
|
// Remove the section that includes the indexPath and check if the cell's indexPath is now nil
|
||||||
|
del->_itemCounts.pop_back();
|
||||||
|
[cn deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section]];
|
||||||
|
XCTAssertNil(cell.indexPath, @"Expected the cell's indexPath to be nil once the section that contains the node is deleted.");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://github.com/facebook/AsyncDisplayKit/issues/2011
|
* https://github.com/facebook/AsyncDisplayKit/issues/2011
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
@implementation RandomCoreGraphicsNode
|
@implementation RandomCoreGraphicsNode
|
||||||
|
|
||||||
|
@synthesize indexPath=_indexPath;
|
||||||
|
|
||||||
+ (UIColor *)randomColor
|
+ (UIColor *)randomColor
|
||||||
{
|
{
|
||||||
CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0
|
CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0
|
||||||
|
|||||||
Reference in New Issue
Block a user