iOS14中SwiftUI按日期分行展示数组数据的实现方案
解决方案:SwiftUI按日期分组展示情绪打卡(iOS14兼容)
步骤1:添加日期分组逻辑
首先在CheckInData类中新增计算属性,将原始打卡数据按自然日分组。核心是把任意时间转换为当天零点作为分组key,确保同一天的打卡归为一组:
class CheckInData: ObservableObject { @Published var arrayWithEmotion: [CheckIn] = [] // 移除可选型,初始化已赋值空数组,避免强制解包 init() { arrayWithEmotion = loadEmotion() // 可选:按时间倒序排列,最新打卡排在最前 arrayWithEmotion.sort { $0.timeAdded > $1.timeAdded } } // 新增:按日期分组的计算属性 var groupedByDate: [Date: [CheckIn]] { let calendar = Calendar.current return Dictionary(grouping: arrayWithEmotion) { checkIn in calendar.startOfDay(for: checkIn.timeAdded) } } // 原有方法保留,仅调整强制解包问题 func addEmotion(emotion: CheckIn) { arrayWithEmotion.append(emotion) arrayWithEmotion.sort { $0.timeAdded > $1.timeAdded } saveEmotion() } func saveEmotion() { if let encoded = try? JSONEncoder().encode(arrayWithEmotion) { UserDefaults.standard.set(encoded, forKey: "emotions") } } func loadEmotion() -> [CheckIn] { if let encoded = UserDefaults.standard.data(forKey: "emotions") { if let decoded = try? JSONDecoder().decode([CheckIn].self, from: encoded) { return decoded } } return [] } }
步骤2:实现按日期分行+分隔线的UI展示
使用SwiftUI的List+Section组合,遍历分组后的日期数据,每个日期组展示标题,下方垂直排列当日情绪,组间自动生成分隔线:
struct EmotionCheckInView: View { @StateObject var checkIn = CheckInData() // 日期格式化器,生成友好的日期文本 private let dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateStyle = .medium // 格式示例:2024/5/20 或 May 20, 2024,可按需调整 return formatter }() var body: some View { List { // 按时间倒序遍历日期分组 ForEach(checkIn.groupedByDate.sorted(by: { $0.key > $1.key }), id: \.key) { date, checkIns in Section(header: Text(dateFormatter.string(from: date))) { // 垂直排列当日的每个情绪 ForEach(checkIns, id: \.timeAdded) { item in Image(item.emotion) .resizable() .frame(width: 20, height: 20) .scaledToFill() .frame(maxWidth: .infinity, alignment: .leading) } } .listRowSeparator(.visible) // 强制显示行分隔线 } } .listStyle(.insetGrouped) // iOS14兼容的分组列表样式,自带组间分隔效果 } }
关键说明
- 无需修改数据模型存空值:只展示有打卡记录的日期即可,无打卡的日期没必要显示,完全不需要在模型中添加空值字段。
- 日期分组核心:
Calendar.startOfDay(for:)将任意时间转为当天零点,确保同一天的打卡被正确归组。 - iOS14兼容性:
List+Section+.insetGrouped是iOS14原生支持的方案,无需额外依赖。 - 安全优化:移除
arrayWithEmotion的可选型,避免后续代码中的强制解包操作。
可选自定义优化
如果需要更个性化的分隔线,可以替换系统分隔线为自定义视图:
// 在情绪视图后添加自定义分隔线 ForEach(checkIns, id: \.timeAdded) { item in Image(item.emotion) .resizable() .frame(width: 20, height: 20) .scaledToFill() .frame(maxWidth: .infinity, alignment: .leading) Divider() .background(Color.gray.opacity(0.3)) .padding(.vertical, 4) }
内容的提问来源于stack exchange,提问作者user19727360
相关产品推荐
相关产品推荐

