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

SwiftUI中筛选Cloud Firestore内当前日期在双时间戳间的日历事件

解决方案

1. 优化数据模型(补充Identifiable必需字段)

原Calendar结构体缺少Identifiable协议要求的id字段,同时为避免与系统Calendar类冲突,重命名结构体并优化解析逻辑:

import FirebaseFirestoreSwift

struct CalendarEvent: Decodable, Identifiable {
    @DocumentID var id: String? // 自动映射Firestore文档ID
    var title: String = ""
    var datebegin: Date = Date()
    var dateend: Date = Date()
}

2. Firestore端精准筛选(减少客户端数据量)

直接在数据库查询阶段过滤出当前时间处于datebegin和dateend之间的文档,比全量拉取后再过滤更高效:

class CalendarViewModel: ObservableObject {
    let db = Firestore.firestore()
    @Published var events = [CalendarEvent]()
    
    init() {
        fetchFilteredEvents()
    }
    
    func fetchFilteredEvents() {
        let now = Date()
        db.collection("calendar")
            // 筛选条件:当前时间 >= datebegin 且 当前时间 <= dateend
            .whereField("datebegin", isLessThanOrEqualTo: now)
            .whereField("dateend", isGreaterThanOrEqualTo: now)
            .getDocuments { snapshot, error in
                guard let snapshot = snapshot, error == nil else {
                    print("拉取数据失败:\(error?.localizedDescription ?? "未知错误")")
                    return
                }
                
                // 用FirestoreDecoder自动解析文档,替代手动赋值
                let events = snapshot.documents.compactMap { doc in
                    try? doc.data(as: CalendarEvent.self)
                }
                
                DispatchQueue.main.async {
                    self.events = events
                }
            }
    }
}

3. 客户端分组与排序

在View中实现按星期几分组、按星期顺序排序的逻辑:

struct HomeView: View {
    @EnvironmentObject var viewModel: CalendarViewModel
    
    // 预设星期顺序,保证分组按周一到周日排列
    private let weekOrder = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
    
    // 静态日期格式化器,避免重复创建提升性能
    private static let weekdayFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "zh_CN")
        formatter.dateFormat = "EEEE"
        return formatter
    }()
    
    // 计算属性:处理分组与排序后的事件列表
    private var groupedEvents: [(weekday: String, events: [CalendarEvent])] {
        // 按星期几分组事件
        let groupedDict = Dictionary(grouping: viewModel.events) { event in
            Self.weekdayFormatter.string(from: event.datebegin)
        }
        
        // 按预设星期顺序排序分组,同时每组内事件按开始时间升序排列
        return weekOrder.compactMap { weekday in
            guard let events = groupedDict[weekday] else { return nil }
            let sortedEvents = events.sorted { $0.datebegin < $1.datebegin }
            return (weekday, sortedEvents)
        }
    }
    
    var body: some View {
        List(groupedEvents, id: \.weekday) { group in
            Section(header: Text(group.weekday).font(.headline)) {
                ForEach(group.events) { event in
                    Text(event.title)
                }
            }
        }
    }
}

关键注意事项

  • 确保Firestore中datebegin和dateend字段为Timestamp类型,否则查询条件会失效;
  • 若需要实时更新事件,可将getDocuments替换为addSnapshotListener,实现数据库变更的实时监听;
  • 若需支持多语言,可调整DateFormatter的locale参数。

内容的提问来源于stack exchange,提问作者user18175514

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 07:06:20