Expo SDK38 iOS端用Calendar.createEventAsync添加日历预约无法获取ID求助
Expo SDK38 日历预约功能无法获取事件ID问题修正
核心错误点
- 权限逻辑错误:原
obtainCalendarPermission函数申请CALENDAR权限未通过时直接return,后续REMINDERS权限申请分支永远无法触发,存在大量不可达代码 - API参数调用错误:
Calendar.getCalendarsAsync()未传入SDK38要求的权限类型参数,默认返回的可写日历列表可能为空Calendar.createEventAsync()第一个参数要求传入日历实例ID,原代码错误传入source ID,是创建失败、无法返回事件ID的核心原因
- 逻辑顺序错误:原代码权限校验逻辑写反,仅在权限不通过时才会执行获取日历列表的操作
- 平台适配逻辑错误:Android端的默认日历过滤规则与iOS不兼容,无法正确获取可写入的本地日历
前置依赖与配置
首先确认导入依赖正确,SDK38需单独安装对应包:
npx expo install expo-permissions expo-calendar
代码开头导入对应模块:
import * as Permissions from 'expo-permissions'; import * as Calendar from 'expo-calendar'; import { Platform, Alert } from 'react-native';
需在app.json的expo配置项中添加权限声明:
{ "expo": { "android": { "permissions": ["READ_CALENDAR", "WRITE_CALENDAR"] }, "ios": { "infoPlist": { "NSCalendarsUsageDescription": "需要访问日历添加预约", "NSRemindersUsageDescription": "需要访问提醒以同步预约" } } } }
修正后完整代码
权限申请函数
async obtainCalendarPermission() { const calendarPerm = await Permissions.getAsync(Permissions.CALENDAR); if (calendarPerm.status !== 'granted') { const askPerm = await Permissions.askAsync(Permissions.CALENDAR); if (askPerm.status !== 'granted') { Alert.alert('日历权限未授予,无法添加预约'); return false; } } // 仅iOS需单独申请提醒权限 if (Platform.OS === 'ios') { const reminderPerm = await Permissions.getAsync(Permissions.REMINDERS); if (reminderPerm.status !== 'granted') { await Permissions.askAsync(Permissions.REMINDERS); } } return true; }
获取可写日历函数
替代原getDefaultCalendarSource,直接返回可写入的日历实例:
async getDefaultWritableCalendar() { // 传入'writer'参数获取所有有写入权限的日历 const calendars = await Calendar.getCalendarsAsync('writer'); const defaultCal = calendars.find(cal => { if (Platform.OS === 'ios') { return cal.source?.name === 'Default' && cal.accessLevel === 'owner'; } return cal.isLocalAccount && cal.accessLevel === 'owner'; }); // 兜底取第一个可写日历 return defaultCal || calendars[0]; }
预约添加函数
async addReservationToCalendar(date) { const hasPermission = await this.obtainCalendarPermission(); if (!hasPermission) return; const targetCalendar = await this.getDefaultWritableCalendar(); if (!targetCalendar) { Alert.alert('未找到可用的可写日历'); return; } const dateMs = Date.parse(date); const startDate = new Date(dateMs); const endDate = new Date(dateMs + 2 * 60 * 60 * 1000); try { // 传入日历实例ID,返回值即为创建成功的事件ID const eventId = await Calendar.createEventAsync(targetCalendar.id, { title: 'Con Fusion Table Reservation', startDate: startDate, endDate: endDate, timeZone: 'Asia/Hong_Kong', location: '121, Clear Water Bay Road, Clear Water Bay, Kowloon, Hong Kong', }); console.log('创建的事件ID:', eventId); return eventId; } catch (e) { console.error('创建预约失败:', e); Alert.alert('添加预约失败,请重试'); } }
注意事项
- 若在Expo Go环境下测试,配置完成后直接运行即可,无需自定义开发构建
- 若获取到的日历列表为空,可先在系统日历App中手动添加一个本地日历后再重试
内容的提问来源于stack exchange,提问作者emekaokoli
相关产品推荐
相关产品推荐

