TableView复杂排序:如何对分组内Cell按时间升序排列?
问题:如何实现分组内Cell按时间升序排列
现有用于TableView分组展示的数组与数据结构如下:
var sections: [SectionContent] = [] var cells: [CellContent] = [] struct SectionContent { let sectionDate: Date let sectionContent: [CellContent] } struct CellContent { let cellDate: Date? var formattedDate: String { guard let text = cellDate else { return "" } return DateFormatter.stringDate.string(from: text) } } extension DateFormatter { static let stringDate: DateFormatter = { let formatterDate = DateFormatter() formatterDate.dateFormat = "MMM d, h:mm a" return formatterDate }() }
目前已通过sections.sort { $0.sectionDate < $1.sectionDate }实现分组按日期升序排序,但需要实现单个分组内的Cell按对应时间升序排列(早时间在上,晚时间在下),现有构造分组的代码如下:
func sortByDate() { sections.removeAll() let dates = cells.reduce(into: Set<Date>()) { result, cells in let date = Calendar.current.startOfDay(for: cells.cellDate!) result.insert(date) } for date in dates { let dateComp = Calendar.current.dateComponents([.year, .month, .day], from: date) var sortedContent: [CellContent] = [] cells.forEach { cells in let contComp = Calendar.current.dateComponents([.year, .month, .day], from: cells.cellDate!) if contComp == dateComp { sortedContent.append(cells) } } let newSection = SectionContent(sectionDate: date, sectionContent: sortedContent) sections.append(newSection) } }
解决方案
只需在构造每个分组的sectionContent时,对筛选出的CellContent数组按cellDate升序排序即可,同时优化原代码中的强制解包问题避免崩溃:
修改后的完整sortByDate方法:
func sortByDate() { sections.removeAll() // 提取所有cell对应的"当天起始时间"作为分组依据 let dates = cells.reduce(into: Set<Date>()) { result, cell in guard let cellDate = cell.cellDate else { return } let dayStart = Calendar.current.startOfDay(for: cellDate) result.insert(dayStart) } for date in dates { let targetDayComp = Calendar.current.dateComponents([.year, .month, .day], from: date) // 筛选当前日期的cell并按时间升序排序 let sortedCells = cells.filter { cell in guard let cellDate = cell.cellDate else { return false } let cellDayComp = Calendar.current.dateComponents([.year, .month, .day], from: cellDate) return cellDayComp == targetDayComp }.sorted { cellA, cellB in // 处理cellDate为nil的情况,将nil的cell放在分组末尾 guard let dateA = cellA.cellDate, let dateB = cellB.cellDate else { return cellA.cellDate != nil && cellB.cellDate == nil } return dateA < dateB } let newSection = SectionContent(sectionDate: date, sectionContent: sortedCells) sections.append(newSection) } // 保持分组整体按日期升序排列 sections.sort { $0.sectionDate < $1.sectionDate } }
核心修改说明:
- 用
filter替代原有的forEach+append逻辑,代码更简洁高效 - 在筛选后链式调用
.sorted,直接对分组内的cell按cellDate升序排序,实现早时间在上的效果 - 替换所有强制解包
!为guard let可选绑定,避免因cellDate为nil导致的运行时崩溃 - 增加了
cellDate为nil的排序规则,确保这类cell不会影响正常排序逻辑(可根据需求调整位置)
内容的提问来源于stack exchange,提问作者CalebGates
相关产品推荐
相关产品推荐

