设计思路
- 长按进入编辑模式:通过添加
UILongPressGestureRecognizer
到 UITableView
,识别长按手势,切换到编辑模式。
- 拖动单元格排序:利用
UITableView
的 UITableViewDragDelegate
和 UITableViewDropDelegate
代理方法实现拖动排序功能。
- 单元格多选及批量删除:使用一个数组记录选中的单元格索引,在编辑模式下,点击单元格更新选中状态。批量删除时,从数据源和
UITableView
中移除选中的单元格。
涉及的代理方法
- 长按手势处理:无特定代理方法,通过手势识别器的回调处理。
- 拖动排序:
tableView:itemsForBeginningDragSession:atIndexPath:
:返回用于开始拖动的 NSItemProvider
。
tableView:performDropWithCoordinator:
:处理放置操作,更新数据源和 UITableView
。
- 多选及批量删除:
tableView:didSelectRowAtIndexPath:
:在编辑模式下,更新选中状态数组。
tableView:commitEditingStyle:forRowAtIndexPath:
:实现删除操作。
数据结构调整
- 数据源:通常是一个数组,存放单元格的数据。
- 选中状态数组:定义一个
NSMutableIndexSet
用于记录选中的单元格索引。
具体的Objective-C代码实现步骤
- 添加长按手势:
UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognized:)];
longPressGestureRecognizer.minimumPressDuration = 0.5;
[self.tableView addGestureRecognizer:longPressGestureRecognizer];
- 长按手势回调:
- (void)longPressGestureRecognized:(UILongPressGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
CGPoint point = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];
if (indexPath) {
// 进入编辑模式
self.tableView.editing = YES;
}
}
}
- 实现拖动排序代理方法:
// 开始拖动
- (NSArray<id<UITableViewDragItem>> *)tableView:(UITableView *)tableView itemsForBeginningDragSession:(id<UIDragSession>)session atIndexPath:(NSIndexPath *)indexPath {
id object = self.dataSource[indexPath.row];
NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithObject:object];
UITableViewDragItem *dragItem = [[UITableViewDragItem alloc] initWithItemProvider:itemProvider];
return @[dragItem];
}
// 处理放置操作
- (void)tableView:(UITableView *)tableView performDropWithCoordinator:(id<UITableViewDropCoordinator>)coordinator {
NSIndexPath *destinationIndexPath = coordinator.destinationIndexPath;
if (!destinationIndexPath) {
NSInteger lastRow = self.dataSource.count - 1;
destinationIndexPath = [NSIndexPath indexPathForRow:lastRow inSection:0];
}
NSArray<id<UITableViewDropItem>> *dropItems = coordinator.items;
for (UITableViewDropItem *dropItem in dropItems) {
NSIndexPath *sourceIndexPath = dropItem.sourceIndexPath;
if (sourceIndexPath.section == destinationIndexPath.section) {
if (sourceIndexPath.row < destinationIndexPath.row) {
for (NSInteger i = sourceIndexPath.row; i < destinationIndexPath.row; i++) {
[self.dataSource exchangeObjectAtIndex:i withObjectAtIndex:i + 1];
}
} else {
for (NSInteger i = sourceIndexPath.row; i > destinationIndexPath.row; i--) {
[self.dataSource exchangeObjectAtIndex:i withObjectAtIndex:i - 1];
}
}
[self.tableView moveRowAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath];
}
}
}
- 实现多选及批量删除:
// 定义选中状态数组
@property (nonatomic, strong) NSMutableIndexSet *selectedIndexSet;
// 初始化选中状态数组
self.selectedIndexSet = [NSMutableIndexSet indexSet];
// 处理单元格选中
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.tableView.editing) {
if ([self.selectedIndexSet containsIndex:indexPath.row]) {
[self.selectedIndexSet removeIndex:indexPath.row];
} else {
[self.selectedIndexSet addIndex:indexPath.row];
}
}
}
// 实现删除操作
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.dataSource removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
// 批量删除
- (void)deleteSelectedRows {
NSArray<NSIndexPath *> *indexPaths = [self.selectedIndexSet indexesPassingTest:^BOOL(NSUInteger idx, BOOL * _Nonnull stop) {
return YES;
}].indexPaths;
[self.dataSource removeObjectsAtIndexes:self.selectedIndexSet];
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.selectedIndexSet removeAllIndexes];
}