From b7d66943d7e2796bff994da131c613d5f3bfe094 Mon Sep 17 00:00:00 2001 From: Adlai Holler Date: Fri, 9 Sep 2016 16:05:47 -0700 Subject: [PATCH] Support UITableView interactive reordering --- AsyncDisplayKit/ASTableView.mm | 22 +++++++++++++++++++++ AsyncDisplayKit/Details/ASDataController.h | 8 ++++++++ AsyncDisplayKit/Details/ASDataController.mm | 19 ++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index 8dc50524..574f8675 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -146,6 +146,8 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; unsigned int asyncDataSourceNumberOfSectionsInTableView:1; unsigned int asyncDataSourceTableViewNodeBlockForRowAtIndexPath:1; unsigned int asyncDataSourceTableViewNodeForRowAtIndexPath:1; + unsigned int asyncDataSourceTableViewCanMoveRowAtIndexPath:1; + unsigned int asyncDataSourceTableViewMoveRowAtIndexPath:1; } _asyncDataSourceFlags; } @@ -301,6 +303,8 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; _asyncDataSourceFlags.asyncDataSourceNumberOfSectionsInTableView = [_asyncDataSource respondsToSelector:@selector(numberOfSectionsInTableView:)]; _asyncDataSourceFlags.asyncDataSourceTableViewNodeForRowAtIndexPath = [_asyncDataSource respondsToSelector:@selector(tableView:nodeForRowAtIndexPath:)]; _asyncDataSourceFlags.asyncDataSourceTableViewNodeBlockForRowAtIndexPath = [_asyncDataSource respondsToSelector:@selector(tableView:nodeBlockForRowAtIndexPath:)]; + _asyncDataSourceFlags.asyncDataSourceTableViewCanMoveRowAtIndexPath = [_asyncDataSource respondsToSelector:@selector(tableView:canMoveRowAtIndexPath:)]; + _asyncDataSourceFlags.asyncDataSourceTableViewMoveRowAtIndexPath = [_asyncDelegate respondsToSelector:@selector(tableView:moveRowAtIndexPath:toIndexPath:)]; // Data source must implement tableView:nodeBlockForRowAtIndexPath: or tableView:nodeForRowAtIndexPath: ASDisplayNodeAssertTrue(_asyncDataSourceFlags.asyncDataSourceTableViewNodeBlockForRowAtIndexPath || _asyncDataSourceFlags.asyncDataSourceTableViewNodeForRowAtIndexPath); @@ -660,6 +664,24 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell"; return [_dataController numberOfRowsInSection:section]; } +- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (_asyncDataSourceFlags.asyncDataSourceTableViewCanMoveRowAtIndexPath) { + return [_asyncDataSource tableView:self canMoveRowAtIndexPath:indexPath]; + } else { + return NO; + } +} + +- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath +{ + if (_asyncDataSourceFlags.asyncDataSourceTableViewMoveRowAtIndexPath) { + [_asyncDataSource tableView:self moveRowAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath]; + } + // Move node after informing data source in case they call nodeAtIndexPath: + [_dataController moveCompletedNodeAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath]; +} + - (void)tableView:(UITableView *)tableView willDisplayCell:(_ASTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { _pendingVisibleIndexPath = indexPath; diff --git a/AsyncDisplayKit/Details/ASDataController.h b/AsyncDisplayKit/Details/ASDataController.h index 7d748663..58e7b35b 100644 --- a/AsyncDisplayKit/Details/ASDataController.h +++ b/AsyncDisplayKit/Details/ASDataController.h @@ -188,6 +188,14 @@ FOUNDATION_EXPORT NSString * const ASDataControllerRowNodeKind; */ - (NSArray *> *)completedNodes; +/** + * Immediately move this item. This is called by ASTableView when the user has finished an interactive + * item move and the table view is requesting a model update. + * + * This must be called on the main thread. + */ +- (void)moveCompletedNodeAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath; + @end NS_ASSUME_NONNULL_END diff --git a/AsyncDisplayKit/Details/ASDataController.mm b/AsyncDisplayKit/Details/ASDataController.mm index e6ec2b76..3183dbcb 100644 --- a/AsyncDisplayKit/Details/ASDataController.mm +++ b/AsyncDisplayKit/Details/ASDataController.mm @@ -898,6 +898,25 @@ NSString * const ASDataControllerRowNodeKind = @"_ASDataControllerRowNodeKind"; return _externalCompletedNodes ? : _completedNodes[ASDataControllerRowNodeKind]; } +- (void)moveCompletedNodeAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath +{ + ASDisplayNodeAssertMainThread(); + if (_externalCompletedNodes != nil) { + NSMutableArray *oldSection = _externalCompletedNodes[indexPath.section]; + ASCellNode *node = oldSection[indexPath.item]; + [oldSection removeObjectAtIndex:indexPath.item]; + [_externalCompletedNodes[newIndexPath.section] insertObject:node atIndex:newIndexPath.item]; + } + + NSMutableArray *internalCompletedNodes = _completedNodes[ASDataControllerRowNodeKind]; + if (internalCompletedNodes != nil) { + NSMutableArray *oldSection = internalCompletedNodes[indexPath.section]; + ASCellNode *node = oldSection[indexPath.item]; + [oldSection removeObjectAtIndex:indexPath.item]; + [internalCompletedNodes[newIndexPath.section] insertObject:node atIndex:newIndexPath.item]; + } +} + #pragma mark - Dealloc - (void)dealloc