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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 14:06:55