You need to enable JavaScript to run this app. Expo SDK38 iOS端用Calendar.createEventAsync添加日历预约无法获取ID求助
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.14 06:45:04