iOS:基于日期对Person数组排序并实现UICollectionView分组
解决Person数组按日期分组排序并适配UICollectionView分组的问题
我来帮你一步步搞定这个需求!核心思路是先按日期天粒度排序Person数组,再按天分组,最后将分组数据适配到UICollectionView的section结构中。以下是具体实现步骤:
1. 基础准备:定义相关结构体(如果还没做的话)
首先假设你的Person结构体是这样的(根据实际情况调整字段):
struct Person { let inscriptionDate: TimeInterval // 时间戳(注意是秒级还是毫秒级,毫秒的话后续要除以1000) // 其他字段:name, age... }
我们还需要一个Section结构体来存储UICollectionView分组的头部标题和对应的数据:
struct Section { let dateTitle: String // 格式为dd/mm/yyyy的日期标题 let people: [Person] // 该日期下的Person数组 }
2. 按日期天粒度排序Person数组
你提到的NSCalendar.compareDate在Swift中可以用Calendar.current.compare(_:to:toGranularity:)替代,它能帮我们忽略时分秒,只比较日期的天维度。
// 先把时间戳转成Date对象(如果是毫秒级时间戳,记得除以1000) func convertTimestampToDate(_ timestamp: TimeInterval) -> Date { return Date(timeIntervalSince1970: timestamp) } // 对Person数组按日期升序排序(旧日期在前,新日期在后) let calendar = Calendar.current let sortedPeople: [Person] = yourOriginalPersonArray.sorted { person1, person2 in let date1 = convertTimestampToDate(person1.inscriptionDate) let date2 = convertTimestampToDate(person2.inscriptionDate) // 比较两个日期的天粒度,判断date1是否在date2之前 return calendar.compare(date1, to: date2, toGranularity: .day) == .orderedAscending }
3. 按日期天分组生成Section数组
排序完成后,我们需要把同一天的Person归为一组,并生成带日期标题的Section:
// 获取某个日期的当天起始时刻(比如2024-05-20 00:00:00),用作分组的唯一标识 func getStartOfDay(for date: Date) -> Date { return calendar.startOfDay(for: date) } // 按当天起始日期分组Person数组 let groupedPeopleDict = Dictionary(grouping: sortedPeople) { person in let date = convertTimestampToDate(person.inscriptionDate) return getStartOfDay(for: date) } // 将分组字典转成有序的Section数组 let dateFormatter = DateFormatter() dateFormatter.dateFormat = "dd/mm/yyyy" // 注意:如果是月份请用MM,小写mm是分钟! dateFormatter.locale = Locale(identifier: "en_US_POSIX") // 避免区域设置影响格式 let sections: [Section] = groupedPeopleDict .sorted { $0.key < $1.key } // 按日期顺序排序分组 .map { (startDate, people) in Section( dateTitle: dateFormatter.string(from: startDate), people: people ) }
4. 适配UICollectionView数据源
现在sections数组已经完全适配UICollectionView的分组需求,直接在数据源方法中使用即可:
// 返回分组数量 func numberOfSections(in collectionView: UICollectionView) -> Int { return sections.count } // 返回每组的Item数量 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return sections[section].people.count } // 返回分组头部视图 func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { guard kind == UICollectionView.elementKindSectionHeader else { return UICollectionReusableView() } let header = collectionView.dequeueReusableSupplementaryView( ofKind: kind, withReuseIdentifier: "YourHeaderReuseID", for: indexPath ) as! YourCustomHeaderView header.titleLabel.text = sections[indexPath.section].dateTitle return header }
关键细节提醒
- 如果你的
inscriptionDate是毫秒级时间戳,记得在convertTimestampToDate方法中除以1000:Date(timeIntervalSince1970: timestamp / 1000) - 日期格式中的
mm代表分钟,如果你需要的是月份,请改成MM(比如dd/MM/yyyy) - 排序方向可以通过修改
.orderedAscending为.orderedDescending来切换(新日期在前)
内容的提问来源于stack exchange,提问作者Ne AS
相关产品推荐
相关产品推荐

