:numberOfRowsInSection如何把一个分区的多行折叠成1行)
SLExpandableTableView源码解析(上)numberOfRowsInSection如何把一个分区的多行折叠成1行【免费下载链接】SLExpandableTableViewSLExpandableTableView is a UITableView subclass that gives you easy access to expandable and collapsable sections by just implementing a few more delegate and dataSource protocols. (iPhone, iPad, iOS)项目地址: https://gitcode.com/gh_mirrors/sl/SLExpandableTableViewSLExpandableTableView 是一款专为 iOS 打造的开源组件它是 UITableView 的子类只需实现几个额外的 DataSource / Delegate 方法就能让列表的分区Section获得一键展开 / 折叠的手风琴效果同时支持 iPhone 与 iPad。本文聚焦源码中一个最巧妙的技巧库如何利用numberOfRowsInSection这个回调把分区里的多行数据折叠成 1 行。 一、这个组件解决了什么问题原生 UITableView 并不会自动提供分区折叠能力——想让某个 Section 收起来你得自己挪动数据、重算行数代码又长又容易出动画 bug。SLExpandableTableView 的思路是把行数的记账权抢过来。它成为 tableView 真正的 dataSource对外再暴露一层自己的协议由它决定每个分区现在显示几行。效果如下图所示黄色单元格是数据行白色带箭头的行就是折叠/展开的开关行对使用方来说只需额外实现 3 个数据源方法定义在 SLExpandableTableView/SLExpandableTableView.hcanExpandSection:—— 这个分区是否可展开needsToDownloadDataForExpandableSection:—— 展开前是否需要先拉数据expandingCellForSection:—— 返回那个开关行单元格的样式 二、关键前提第 0 行被征用了看懂折叠原理前先要知道库的一个约定在可展开的分区里row 0 永远不是你的数据行而是那个展开/折叠开关行。你的数据从 row 1 开始排。看示例工程 Tests/SLExpandableTableViewTests/SLExpandableTableViewController.m 中的实现就很清楚一个分区有 4 条数据但返回的行数是dataArray.count 1多出来的那一行就是给开关行留位置。相应地库重写了cellForRowAtIndexPath:SLExpandableTableView/SLExpandableTableView.m 第 436-460 行当indexPath.row 0且该分区可展开时它不再询问你的数据源而是直接返回你通过expandingCellForSection:提供的开关行并根据当前状态把它摆成已展开或已折叠的样式。 三、核心拆解numberOfRowsInSection 的折叠魔法真正的魔术发生在库自己实现的这个回调里SLExpandableTableView/SLExpandableTableView.m 第 415-434 行逻辑浓缩后就这几行if ([self.myDataSource tableView:self canExpandSection:section]) { if ([self.myDataSource tableView:tableView numberOfRowsInSection:section] 0) { return 0; // ① 空分区直接返回 0 } self.expandableSectionsDictionary[key] YES; if ([self.showingSectionsDictionary[key] boolValue]) { return [self.myDataSource tableView:tableView numberOfRowsInSection:section]; // ② 已展开返回真实行数 } else { return 1; // ③ 未展开只返回 1 行 } }三步拆解先问你的数据源这个分区能不能展开不能就原样透传真实行数完全不干预。能展开则登记状态把该分区记入expandableSectionsDictionary供点击回调和单元格渲染时查询。按状态谎报行数如果该分区当前没有展开showingSectionsDictionary为 NO就向 UITableView 报告这个分区只有 1 行——于是屏幕上只剩下开关行其余多行被整体藏了起来。这就是标题的答案折叠不是隐藏单元格而是让 UITableView 根本不知道那些行的存在。展开时把行数改回真实值配合插入行动画视觉上的展开就完成了。为了支撑这套记账库内部维护了 4 个状态字典SLExpandableTableView/SLExpandableTableView.h 第 63-66 行字典作用expandableSectionsDictionary记录哪些分区可展开在 numberOfRowsInSection 回调中顺手写入showingSectionsDictionary记录分区当前是展开还是折叠是折叠判断的依据downloadingSectionsDictionary记录哪些分区正在等待数据下载用来在开关行上显示 loadinganimatingSectionsDictionary记录哪些分区正在播放动画用于区分普通的 willDisplayCell 回调注意一个小细节reloadData时库会清空这些状态reloadDataAndResetExpansionStates:第 337-339、150-154 行全部回到折叠态——因为旧索引对应的状态已经不可信了。 四、点击后的展开与折叠动画简析折叠成 1 行只是静态的一半另一半是用户点击开关行后的动画处理didSelectRowAtIndexPath:第 385-411 行点中的是可展开分区的 row 0已展开则调collapseSection:,未展开则调expandSection:点中的是数据行row 0原样转发给你自己的 delegate业务逻辑不受影响。collapseSection:第 268-328 行的动画做法在beginUpdates/endUpdates事务里把 row 1 到 row N-1 一次性deleteRowsAtIndexPaths:删掉同时把开关行切回折叠样式expandSection:第 201-266 行则是反过来insertRowsAtIndexPaths:。默认动画为UITableViewRowAnimationFadereloadAnimation第 134 行。还有一个性能保险丝maximumRowCountToStillUseAnimationWhileExpanding默认NSIntegerMax。当展开行数超过阈值时库会放弃逐行动画直接整体reloadData避免大分区卡顿。⚠️ 五、新手必看的 5 个坑数据源行数必须 1可展开分区里要给开关行留位置否则展开后的行数对不上动画会崩。row 0 没有选择回调头文件第 78 行明确说明可展开分区的 row 0 不会再触发didSelectRowAtIndexPath:回调不要在上面挂跳转逻辑。别直接读tableView.dataSourcegetter它返回的是库自己要访问自己的数据源请用myDataSource头文件第 82-84 行有专门注释。懒加载要闭环声明需要下载数据后成功后调用expandSection:animated:失败调用cancelDownloadInSection:否则开关行会一直停在 loading 态。reloadData 会重置折叠状态刷新数据后所有分区回到折叠态且可展开标记会被重新询问属于预期行为。 六、核心文件速查文件说明SLExpandableTableView/SLExpandableTableView.h对外接口3 个数据源协议方法 展开/折叠公开方法SLExpandableTableView/SLExpandableTableView.m核心实现行数折叠、点击分发、展开/折叠动画Tests/SLExpandableTableViewTests/SLExpandableTableViewController.m完整示例含懒加载下载的分区列表演示Tests/Podfile通过 CocoaPods 引入的依赖示例SLExpandableTableView.podspec组件的 CocoaPods 发布配置到这里折叠藏行的原理已经讲透展开动画的完整时序、下载态与状态字典的交互细节留待源码解析下继续。【免费下载链接】SLExpandableTableViewSLExpandableTableView is a UITableView subclass that gives you easy access to expandable and collapsable sections by just implementing a few more delegate and dataSource protocols. (iPhone, iPad, iOS)项目地址: https://gitcode.com/gh_mirrors/sl/SLExpandableTableView创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考