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

Swift/SwiftUI中如何获取指定日历的当日事件?

解决方案

你的代码存在两个关键问题:一是异步获取事件的逻辑错误导致UI无法拿到数据,二是未实现指定日历的筛选。以下是修复后的完整代码,附带关键修改说明:

import SwiftUI
import EventKit

struct TodayView: View {
    // 用@State存储事件数组,更新时自动触发UI刷新
    @State private var events: [EKEvent] = []
    // 保持EKEventStore实例,避免重复创建
    private let eventStore = EKEventStore()
    
    var body: some View {
        NavigationView {
            ZStack {
                Color.gray.opacity(0.1) // 示例背景色,可替换为你自己的background定义
                ScrollView(.vertical) {
                    VStack(spacing: 12) {
                        if events.isEmpty {
                            Text("今日无课程事件")
                                .foregroundColor(.secondary)
                                .padding()
                        } else {
                            ForEach(events, id: \.self) { event in
                                VStack(alignment: .leading) {
                                    Text(event.title)
                                        .font(.headline)
                                    Text(event.startDate.formatted(date: .omitted, time: .shortened))
                                        .font(.caption)
                                        .foregroundColor(.secondary)
                                }
                                .padding()
                                .background(Color.white)
                                .cornerRadius(8)
                                .shadow(radius: 2)
                            }
                        }
                    }
                    .padding()
                }
            }
            .navigationTitle("今日课程")
            .onAppear(perform: fetchTodayClassEvents) // 视图出现时触发事件获取
        }
    }
    
    private func fetchTodayClassEvents() {
        eventStore.requestAccess(to: .event) { [weak self] granted, error in
            guard let self = self else { return }
            
            if let error = error {
                print("权限请求出错:\(error.localizedDescription)")
                return
            }
            
            guard granted else {
                print("日历权限被拒绝,请在设置中开启")
                DispatchQueue.main.async {
                    self.events = []
                }
                return
            }
            
            // 1. 找到名为"All Classes"的目标日历
            guard let targetCalendar = self.eventStore.calendars(for: .event).first(where: { $0.title == "All Classes" }) else {
                print("未找到名为All Classes的日历")
                DispatchQueue.main.async {
                    self.events = []
                }
                return
            }
            
            // 2. 构造当日的时间范围(从今日0点到明日0点)
            let calendar = Calendar.current
            let startOfDay = calendar.startOfDay(for: Date())
            let endOfDay = calendar.date(byAdding: .day, value: 1, to: startOfDay)!
            
            // 3. 创建仅查询目标日历的事件谓词
            let predicate = self.eventStore.predicateForEvents(
                withStart: startOfDay,
                end: endOfDay,
                calendars: [targetCalendar]
            )
            
            // 4. 获取匹配的事件并更新UI
            let fetchedEvents = self.eventStore.events(matching: predicate)
            // 按开始时间排序事件
            let sortedEvents = fetchedEvents.sorted { $0.startDate < $1.startDate }
            
            DispatchQueue.main.async {
                self.events = sortedEvents
            }
        }
    }
}

// 预览
struct TodayView_Previews: PreviewProvider {
    static var previews: some View {
        TodayView()
    }
}

关键修改说明

  • 异步逻辑修复:
    移除全局变量,改用@State private var events存储事件,异步获取完成后在主线程更新该变量,SwiftUI会自动刷新视图。
    用onAppear触发事件获取,替代init中执行,确保视图初始化完成后再处理权限和数据请求。

  • 指定日历筛选:
    通过eventStore.calendars(for: .event)获取所有可访问的事件日历,再用first(where:)筛选出标题为"All Classes"的日历。
    创建predicateForEvents时,将calendars参数设为目标日历数组,实现仅查询该日历下的事件。

  • 时间范围优化:
    把原来的跨三天范围改成精确的当日区间(今日0点到明日0点),避免查询到非当日的事件。

  • 异常与体验优化:
    添加事件为空时的提示文本,给事件增加样式和时间显示,同时处理权限被拒绝、找不到目标日历等异常场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 17:57:27