MST

星途 面试题库

面试题:Objective-C实现UITableView复杂交互逻辑的设计与实现

假设要在Objective-C开发的iOS应用的UITableView中实现一种复杂交互逻辑:长按单元格进入编辑模式,在编辑模式下可以拖动单元格进行排序,同时支持单元格的多选及批量删除功能。请详细描述整个设计思路,包括涉及的代理方法、数据结构调整,以及具体的Objective-C代码实现步骤。
44.5万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 长按进入编辑模式:通过添加 UILongPressGestureRecognizerUITableView,识别长按手势,切换到编辑模式。
  2. 拖动单元格排序:利用 UITableViewUITableViewDragDelegateUITableViewDropDelegate 代理方法实现拖动排序功能。
  3. 单元格多选及批量删除:使用一个数组记录选中的单元格索引,在编辑模式下,点击单元格更新选中状态。批量删除时,从数据源和 UITableView 中移除选中的单元格。

涉及的代理方法

  1. 长按手势处理:无特定代理方法,通过手势识别器的回调处理。
  2. 拖动排序
    • tableView:itemsForBeginningDragSession:atIndexPath::返回用于开始拖动的 NSItemProvider
    • tableView:performDropWithCoordinator::处理放置操作,更新数据源和 UITableView
  3. 多选及批量删除
    • tableView:didSelectRowAtIndexPath::在编辑模式下,更新选中状态数组。
    • tableView:commitEditingStyle:forRowAtIndexPath::实现删除操作。

数据结构调整

  1. 数据源:通常是一个数组,存放单元格的数据。
  2. 选中状态数组:定义一个 NSMutableIndexSet 用于记录选中的单元格索引。

具体的Objective-C代码实现步骤

  1. 添加长按手势
UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGestureRecognized:)];
longPressGestureRecognizer.minimumPressDuration = 0.5;
[self.tableView addGestureRecognizer:longPressGestureRecognizer];
  1. 长按手势回调
- (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;
        }
    }
}
  1. 实现拖动排序代理方法
// 开始拖动
- (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];
        }
    }
}
  1. 实现多选及批量删除
// 定义选中状态数组
@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];
}