EventKit如何获取EKReminder子任务对应的父任务层级关系
EventKit获取提醒事项父子层级关系方案
EKReminder官方公开文档未直接标注父子任务关联属性,是因为该层级能力的公开API在较新系统版本才正式对外提供,具体实现方式分两种场景:
系统版本适配说明
- iOS 17、macOS 14 及以上版本:苹果已正式开放公开属性,可直接调用,无审核风险
- 低于上述版本的系统:任务层级关系存储在EventKit内部私有字段中,可通过KVC方式读取,但该方式调用非公开API,上架App Store存在审核被拒风险,仅建议自用、内部分发场景使用
具体实现代码
首先给EKReminder写扩展,兼容不同版本的层级读取逻辑:
import EventKit extension EKReminder { /// 获取当前提醒的父任务,顶层任务返回nil var parentReminderTask: EKReminder? { if #available(iOS 17.0, macOS 14.0, *) { return self.parentReminder } else { return self.value(forKey: "parent") as? EKReminder } } /// 获取当前提醒下的所有直接子任务 var reminderSubtasks: [EKReminder] { if #available(iOS 17.0, macOS 14.0, *) { return self.subtasks ?? [] } else { return self.value(forKey: "subtasks") as? [EKReminder] ?? [] } } }
原有拉取提醒的逻辑不需要修改,fetchReminders返回的结果已经包含所有层级的提醒事项,拉取完成后直接遍历读取关联属性即可,示例修改如下:
func fetchAllReminders(for store:EKEventStore) { let predicate: NSPredicate? = store.predicateForIncompleteReminders(withDueDateStarting: nil, ending: nil, calendars: nil) store.fetchReminders(matching: predicate!, completion: { (reminders: [EKReminder]?) -> Void in guard let reminders = reminders else { assertionFailure("No reminders found") return } if reminders.isEmpty { print("No reminders found") return } // 先筛选所有顶层任务(无父任务的项) let topLevelReminders = reminders.filter { $0.parentReminderTask == nil } for reminder in topLevelReminders { print("=== 顶层任务:\(reminder.title ?? "No title") ===") print("所属日历: \(reminder.calendar.title)") if reminder.hasNotes { print("备注: \(reminder.notes ?? "No Notes")") } // 遍历当前顶层任务的子任务 let subtasks = reminder.reminderSubtasks if !subtasks.isEmpty { print("子任务列表:") for (index, subtask) in subtasks.enumerated() { print("\(index+1). \(subtask.title ?? "无标题")") } } } }) }
效果参考

提示:如果你的应用需要上架App Store,建议在低版本系统中隐藏任务层级展示能力,仅在iOS17+/macOS14+系统中使用公开API读取父子关系,避免因调用私有接口被审核驳回。
内容的提问来源于stack exchange,提问作者Raptor
相关产品推荐
相关产品推荐

