mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +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 (weak, nonatomic, nullable) ASDisplayNode *owningNode;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -108,6 +108,20 @@ typedef NS_ENUM(NSUInteger, ASCellNodeVisibilityEvent) {
|
||||
*/
|
||||
@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
|
||||
* these methods (e.g. for highlighting) requires the super method be called.
|
||||
|
||||
@@ -36,6 +36,12 @@
|
||||
ASDisplayNode *_viewControllerNode;
|
||||
UIViewController *_viewController;
|
||||
BOOL _suspendInteractionDelegate;
|
||||
|
||||
struct {
|
||||
unsigned int isTableNode:1;
|
||||
unsigned int isCollectionNode:1;
|
||||
} _owningNodeType;
|
||||
|
||||
}
|
||||
|
||||
@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;
|
||||
{
|
||||
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 ignored "-Wobjc-missing-super-calls"
|
||||
|
||||
|
||||
@@ -233,15 +233,14 @@
|
||||
|
||||
- (void)_populateSupplementaryNodesOfKind:(NSString *)kind withSections:(NSIndexSet *)sections mutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts
|
||||
{
|
||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
||||
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
|
||||
[sections enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
for (NSUInteger sec = range.location; sec < NSMaxRange(range); sec++) {
|
||||
NSUInteger itemCount = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:sec];
|
||||
for (NSUInteger i = 0; i < itemCount; i++) {
|
||||
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
|
||||
{
|
||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
||||
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
|
||||
NSMutableIndexSet *sections = [NSMutableIndexSet indexSet];
|
||||
for (NSIndexPath *indexPath in indexPaths) {
|
||||
@@ -262,13 +260,13 @@
|
||||
NSUInteger itemCount = [self.collectionDataSource dataController:self supplementaryNodesOfKind:kind inSection:sec];
|
||||
for (NSUInteger i = 0; i < itemCount; i++) {
|
||||
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;
|
||||
if (_dataSourceImplementsSupplementaryNodeBlockOfKindAtIndexPath) {
|
||||
@@ -283,7 +281,7 @@
|
||||
indexPath:indexPath
|
||||
supplementaryElementKind:kind
|
||||
constrainedSize:constrainedSize
|
||||
environmentTraitCollection:environmentTraitCollection];
|
||||
environment:environment];
|
||||
[contexts addObject:context];
|
||||
}
|
||||
|
||||
|
||||
@@ -476,8 +476,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
|
||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
||||
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
|
||||
std::vector<NSInteger> counts = [self itemCountsFromDataSource];
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
||||
@@ -493,7 +492,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
indexPath:indexPath
|
||||
supplementaryElementKind:nil
|
||||
constrainedSize:constrainedSize
|
||||
environmentTraitCollection:environmentTraitCollection]];
|
||||
environment:environment]];
|
||||
}
|
||||
}
|
||||
}];
|
||||
@@ -743,8 +742,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
NSArray *sortedIndexPaths = [indexPaths sortedArrayUsingSelector:@selector(compare:)];
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [[NSMutableArray alloc] initWithCapacity:indexPaths.count];
|
||||
|
||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
||||
__weak id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
|
||||
for (NSIndexPath *indexPath in sortedIndexPaths) {
|
||||
ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath];
|
||||
@@ -753,7 +751,7 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind";
|
||||
indexPath:indexPath
|
||||
supplementaryElementKind:nil
|
||||
constrainedSize:constrainedSize
|
||||
environmentTraitCollection:environmentTraitCollection]];
|
||||
environment:environment]];
|
||||
}
|
||||
|
||||
ASInsertElementsIntoMultidimensionalArrayAtIndexPaths(_nodeContexts[ASDataControllerRowNodeKind], sortedIndexPaths, contexts);
|
||||
|
||||
@@ -24,13 +24,14 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, readonly, strong) NSIndexPath *indexPath;
|
||||
@property (nonatomic, readonly, copy, nullable) NSString *supplementaryElementKind;
|
||||
@property (nonatomic, readonly, assign) ASSizeRange constrainedSize;
|
||||
@property (weak, nonatomic) id<ASEnvironment> environment;
|
||||
@property (nonatomic, readonly, assign) ASEnvironmentTraitCollection environmentTraitCollection;
|
||||
|
||||
- (instancetype)initWithNodeBlock:(ASCellNodeBlock)nodeBlock
|
||||
indexPath:(NSIndexPath *)indexPath
|
||||
supplementaryElementKind:(nullable NSString *)supplementaryElementKind
|
||||
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
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
indexPath:(NSIndexPath *)indexPath
|
||||
supplementaryElementKind:(nullable NSString *)supplementaryElementKind
|
||||
constrainedSize:(ASSizeRange)constrainedSize
|
||||
environmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection
|
||||
environment:(id<ASEnvironment>)environment
|
||||
{
|
||||
NSAssert(nodeBlock != nil && indexPath != nil, @"Node block and index path must not be nil");
|
||||
self = [super init];
|
||||
@@ -40,7 +40,8 @@
|
||||
_indexPath = indexPath;
|
||||
_supplementaryElementKind = [supplementaryElementKind copy];
|
||||
_constrainedSize = constrainedSize;
|
||||
_environmentTraitCollection = environmentTraitCollection;
|
||||
_environment = environment;
|
||||
_environmentTraitCollection = environment.environmentTraitCollection;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -57,6 +58,7 @@
|
||||
}
|
||||
node.cachedIndexPath = _indexPath;
|
||||
node.supplementaryElementKind = _supplementaryElementKind;
|
||||
node.owningNode = (ASDisplayNode *)_environment;
|
||||
ASEnvironmentStatePropagateDown(node, _environmentTraitCollection);
|
||||
_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
|
||||
*
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
|
||||
@implementation RandomCoreGraphicsNode
|
||||
|
||||
@synthesize indexPath=_indexPath;
|
||||
|
||||
+ (UIColor *)randomColor
|
||||
{
|
||||
CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0
|
||||
|
||||
Reference in New Issue
Block a user