You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Objective-C中实现最多n级的可展开折叠多级UITableView

通用多级可展开折叠UITableView实现方案(Objective-C)

1. 核心通用节点模型设计

首先需要定义通用节点模型,兼容任意嵌套深度的数组/字典结构,运行时动态生成层级:

  • 新建NodeModel节点类,核心属性如下:
    • nodeId:节点唯一标识,用于快速定位节点
    • parentId:父节点唯一标识,根节点可设为nil
    • level:当前节点层级,根节点默认值为0,每向下嵌套一级自动+1
    • isExpanded:布尔值,标记当前节点是否处于展开状态
    • subNodes:数组类型,存储当前节点的所有子节点模型
    • rawData:id类型,存储当前节点对应的原始字典/数组数据,供业务层自定义渲染使用
  • 新增递归解析方法,将任意嵌套的原始数据转换为节点树结构:
// NodeModel.h 头文件定义
@interface NodeModel : NSObject
@property (nonatomic, copy) NSString *nodeId;
@property (nonatomic, copy) NSString *parentId;
@property (nonatomic, assign) NSInteger level;
@property (nonatomic, assign) BOOL isExpanded;
@property (nonatomic, strong) NSArray <NodeModel *>*subNodes;
@property (nonatomic, strong) id rawData;

/// 递归解析嵌套数据生成节点树
/// @param nestedData 原始嵌套数组/字典
/// @param parentId 父节点ID,根节点传nil
/// @param level 当前层级,根节点传0
+ (NSArray <NodeModel *>*)parseNestedData:(id)nestedData parentId:(NSString *)parentId currentLevel:(NSInteger)level;
@end

解析方法实现时只需判断当前传入的原始数据类型是数组还是字典,递归生成子节点即可,无需提前限制层级上限。

2. UITableView数据源处理

控制器内维护两个数组即可实现动态展示:

  • originalNodeTree:存储完整的节点树结构,数据结构始终不变
  • displayNodes:一维数组,仅存储当前需要展示的节点,和UITableView的行一一对应,只包含已展开的节点链
  • 节点展开/折叠时只需更新displayNodes数组,无需修改原始节点树

3. 展开折叠交互实现

点击cell时通过局部刷新实现动画效果,无需 reload 整个列表:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NodeModel *currentNode = self.displayNodes[indexPath.row];
    // 无下级节点直接返回,不处理交互
    if (currentNode.subNodes.count == 0) return;
    
    currentNode.isExpanded = !currentNode.isExpanded;
    NSMutableArray *updateIndexPaths = [NSMutableArray array];
    NSInteger currentPosition = indexPath.row;
    
    if (currentNode.isExpanded) {
        // 展开状态:递归获取当前节点下所有需要展示的子节点,插入到displayNodes
        NSArray *addSubNodes = [self getAllVisibleSubNodesOfNode:currentNode];
        [self.displayNodes insertObjects:addSubNodes atIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(currentPosition + 1, addSubNodes.count)]];
        // 生成插入对应的indexPath
        for (NSInteger i = 0; i < addSubNodes.count; i++) {
            [updateIndexPaths addObject:[NSIndexPath indexPathForRow:currentPosition + 1 + i inSection:0]];
        }
        [tableView insertRowsAtIndexPaths:updateIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
    } else {
        // 折叠状态:计算当前节点下所有需要移除的子节点数量,从displayNodes删除
        NSInteger removeCount = [self countOfAllSubNodesUnderNode:currentNode];
        [self.displayNodes removeObjectsInRange:NSMakeRange(currentPosition + 1, removeCount)];
        // 生成删除对应的indexPath
        for (NSInteger i = 0; i < removeCount; i++) {
            [updateIndexPaths addObject:[NSIndexPath indexPathForRow:currentPosition + 1 + i inSection:0]];
        }
        [tableView deleteRowsAtIndexPaths:updateIndexPaths withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

4. Cell动态适配

  • 自定义NestedTableViewCell,根据节点的level属性动态计算左侧缩进距离,实现层级视觉区分
  • 根据节点的isExpanded状态切换展开/折叠箭头图标
  • 通过节点的rawData属性渲染业务需要的文本、图片等自定义内容

注意事项

  • 节点唯一ID需要确保全局唯一,避免递归查找节点时出错,可增加最大嵌套深度限制避免异常的无限嵌套导致死循环
  • 数据量较大(千条以上)时可将displayNodes的更新逻辑放到子线程处理,避免阻塞主线程
  • 如需支持多section展示,只需在节点模型中增加section标识字段即可扩展,核心逻辑无需修改

内容的提问来源于stack exchange,提问作者Sumit_VE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 23:48:02