Swift/SwiftUI:如何跟踪提醒应用中列表的编辑变更?
监听提醒列表编辑变更以更新SwiftUI视图
首先纠正一个误区:.EKEventStoreChanged通知实际上会响应提醒列表(EKCalendar)的名称、颜色等编辑操作,你遇到的问题大概率是没有在回调里正确触发视图更新或重新拉取最新数据。以下是具体的解决思路和代码实现:
基础方案:重新拉取全部数据触发视图刷新
如果不需要精准定位单个变更的列表,最简单的方式是在收到通知后重新获取所有提醒列表数据,结合SwiftUI的@Published属性自动刷新视图:
1. 实现ViewModel管理数据与通知监听
class ReminderListViewModel: ObservableObject { @Published var reminderLists: [EKCalendar] = [] private let eventStore = ReminderManager.shared.eventStore init() { fetchReminderLists() setupNotificationObserver() } private func setupNotificationObserver() { NotificationCenter.default.addObserver( self, selector: #selector(onStoreChanged), name: .EKEventStoreChanged, object: eventStore ) } @objc private func onStoreChanged() { // 收到通知后重新拉取最新数据 fetchReminderLists() } private func fetchReminderLists() { let calendars = eventStore.calendars(for: .reminder) // 确保在主队列更新UI相关数据 DispatchQueue.main.async { self.reminderLists = calendars } } deinit { // 销毁时移除观察者,避免内存泄漏 NotificationCenter.default.removeObserver(self) } }
2. 在SwiftUI视图中使用ViewModel
struct ReminderListView: View { @StateObject private var viewModel = ReminderListViewModel() var body: some View { List(viewModel.reminderLists) { calendar in HStack { Circle() .fill(Color(calendar.color)) .frame(width: 16, height: 16) Text(calendar.title) } } } }
进阶方案:精准监听单个列表的变更
如果需要只更新变化的列表(避免全量刷新),可以额外监听.EKCalendarChangedNotification,它会携带具体变更的日历对象:
在ViewModel的setupNotificationObserver方法中添加:
private func setupNotificationObserver() { // 保留原有全局监听 NotificationCenter.default.addObserver( self, selector: #selector(onStoreChanged), name: .EKEventStoreChanged, object: eventStore ) // 添加单个日历变更监听 NotificationCenter.default.addObserver( self, selector: #selector(onCalendarChanged(_:)), name: .EKCalendarChangedNotification, object: nil ) } @objc private func onCalendarChanged(_ notification: Notification) { guard let updatedCalendar = notification.object as? EKCalendar, updatedCalendar.type == .reminder else { return } // 找到本地列表中对应的项并更新 if let index = reminderLists.firstIndex(where: { $0.calendarIdentifier == updatedCalendar.calendarIdentifier }) { DispatchQueue.main.async { self.reminderLists[index] = updatedCalendar } } }
注意事项
- 确保已提前向用户请求提醒访问权限,否则无法获取和监听日历数据;
- 用
@StateObject(iOS 14+)或ObservedObject管理ViewModel,确保视图能响应@Published属性的变化。
内容的提问来源于stack exchange,提问作者khsadkj
相关产品推荐
相关产品推荐

