fetchReminder拉取系统自带提醒时EKReminder的startDateComponents为nil
EKReminder 拉取时startDateComponents为nil的核心原因
- 该异常和当前的拉取流程没有关联,本质是iOS系统内置提醒应用与第三方应用在EKReminder数据写入时的字段落位逻辑差异导致的:
- 从iOS 13重构提醒事项底层存储逻辑开始,系统自带的「提醒事项」应用创建带日期触发规则的提醒时,不会向
startDateComponents、endDateComponents字段写入任何值 - 很多开发者遇到这个问题的诱因是参考了iOS 12及更早版本的旧开发文档:那个时期系统提醒应用确实会将触发时间写入
startDateComponents字段,系统在重构存储后没有做旧字段的向下兼容写入,才会出现老代码读取系统提醒拿不到值、读取第三方提醒完全正常的现象 - 系统侧会将不同类型的日期触发规则,分别存储在两个专属字段里:
- 仅配置了日期(无具体时间点)的触发规则,会写入
dueDateComponents字段 - 配置了具体时间点的触发规则(比如“3天后下午3点提醒”),会转换为EKAlarm对象,将触发时间存在关联EKAlarm的
absoluteDate属性中
- 仅配置了日期(无具体时间点)的触发规则,会写入
- 从iOS 13重构提醒事项底层存储逻辑开始,系统自带的「提醒事项」应用创建带日期触发规则的提醒时,不会向
- 第三方应用创建的同类提醒能正常读到
startDateComponents值,是因为绝大多数第三方应用在写入EKReminder时,会兼容旧版本的字段约定:只要配置了日期触发,就会同时给startDateComponents赋值,和系统内置应用的写入逻辑并不一致,这才造成了“同类型提醒不同字段表现”的错觉。
读取兼容修正方案
- 拉取EKReminder时,不要将
startDateComponents作为判断是否存在日期触发的唯一依据,按照官方约定的优先级做字段兼容读取即可:- 优先读取
dueDateComponents,覆盖系统内置提醒的纯日期类触发场景 - 遍历提醒关联的
alarms数组,读取每个EKAlarm的absoluteDate,覆盖系统内置提醒的带具体时间点的触发场景 - 回退读取
startDateComponents,用于兼容旧版本第三方应用写入的、没有将触发时间落到上述两个位置的老格式数据
- 优先读取
内容的提问来源于stack exchange,提问作者Merkurial
相关产品推荐
相关产品推荐

