Expo Calendar重复事件统一URL问题:寻求渐进式训练动态deep link的可行方案
Expo Calendar重复事件统一URL问题:寻求渐进式训练动态deep link的可行方案
我之前做健身类App的时候刚好踩过这个坑!系统日历(不管苹果还是谷歌)的重复事件确实天生就不支持给每个实例单独分配不同的deeplink,这是硬限制绕不开,但咱们可以换个思路——不用跟日历的规则死磕,把逻辑移到App端来处理,既能保留重复事件的原生UX,又能实现你要的渐进式训练强度计算。
方案1:App端基于事件起始日期计算乘数(最推荐)
这是最干净、最不hack的方案,完全保留原生重复事件的所有UX:
- 只创建单个标准重复事件,deeplink用固定的
myapp://workout/monday,不带任何参数 - 当用户点击这个deeplink打开你的App时,通过Expo的
Linking模块拿到训练类型(比如monday),再调用Calendar.getEventById获取这个重复事件的原始创建起始日期 - 在App内计算当前实例是第几周:用当前打开的事件实例日期减去起始日期,除以7天的毫秒数,取整数后加1就是
multiplier(比如第1周是1,第2周是2,以此类推) - 关键:把每个训练类型对应的起始日期存在你的App本地存储或者后端用户数据里,比如给用户的“周一训练”绑定一个
start_date: 2024-05-06 - 注意点:如果用户手动修改了某个重复实例的日期,你可以在App里做判断——如果当前实例日期和计算出来的预期日期偏差超过1天,就给用户弹出提示:“检测到训练日期已修改,是否调整本周训练强度?”,让用户选择是按原计划还是按新日期计算
方案2:利用事件备注/自定义字段存储规则,动态计算乘数
这个方案比第一个更灵活,适合需要中途调整训练节奏的场景:
- 还是创建单个重复事件,deeplink用固定的
myapp://workout/monday - 在事件的备注栏或者Expo Calendar支持的自定义扩展字段里,存储这个训练的核心规则,比如用简洁格式写
20240506_monday(起始日期+训练类型) - 用户点击deeplink打开App后,先调用
Calendar.getEventById读取事件的备注内容,解析出起始日期和训练类型,再结合当前实例的日期算出multiplier - 优化点:为了避免用户误改备注里的内容,可以把规则做简单的转码(比如Base64),或者用用户看不懂的压缩格式,用户看到也不会乱改
- 优点:规则存在事件本身里,不用依赖App本地存储,就算用户换设备,只要同步了日历事件,就能正确计算强度
方案3:混合式妥协方案——保留重复事件UX,按需生成单个覆盖事件
如果你的需求必须让每个实例的deeplink本身带参数(比如用户要分享训练链接给朋友),可以用这个平衡方案:
- 先创建一个标准的重复事件,deeplink设为默认的
myapp://workout/monday - 在App里给用户提供一个“确认本周训练强度”的功能,当用户点击后,App自动在对应日期创建一个覆盖式的单个事件(设置为“显示为忙碌”,覆盖原重复事件),这个单个事件的deeplink带对应的
multiplier参数,比如myapp://workout/monday?multiplier=2 - 平时用户在日历里看到的是正常的重复事件,只有当用户确认过的周数,才会被单个事件覆盖,既保留了重复事件的原生UX,又能实现带参数的deeplink
- 优点:用户感知不到复杂的逻辑,只有当需要的时候才触发单个事件创建,同时支持分享带参数的训练链接
实操小提示
- 用Expo的
Linking模块处理deeplink:const { query, path } = Linking.parseInitialURL();可以拿到deeplink的路径和参数 - 调用
Calendar.getEventById时,要注意获取事件的startDate和notes字段,这些是计算的核心 - 计算周数的时候,用时间戳相减是最稳妥的方式,能避免跨月跨年的问题,比如:
const startTimestamp = new Date(startDate).getTime(); const currentTimestamp = new Date(currentEventDate).getTime(); const weekDiff = Math.floor((currentTimestamp - startTimestamp) / (7 * 24 * 60 * 60 * 1000)); const multiplier = weekDiff + 1;
其实核心思路就是不要让日历承担动态参数的存储,把计算逻辑移到App端,这样既不用放弃重复事件的原生UX,又能实现你要的渐进式训练强度。我自己做的健身App用的是方案1,用户反馈非常好,完全感觉不到背后的逻辑,而且维护起来特别简单。
内容来源于stack exchange
相关产品推荐
相关产品推荐

