You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

macOS Big Sur下Swift命令行工具使用EventKit获取日历权限异常问题

问题描述

我正尝试在macOS Big Sur系统上使用Xcode 12.5.1开发一款Swift语言的命令行小工具,用于访问并展示日历事件。我已经查阅了EKEventStore官方文档,编写了最简测试代码:

import Foundation
import EventKit

var store = EKEventStore()

我已开启沙箱功能,添加了日历权限及沙箱对应的entitlement配置;也在Info.plist文件中补充了Privacy - Calendars Usage Description项并填写了对应说明值;同时在构建设置中将Create Info.plist Section in Binary设置为Yes。

但完成上述所有配置后,仅一行核心代码的应用始终无法成功初始化EKEventStore(),报出如下错误:

2021-09-17 23:39:24.609490-0700 nextzoom[51558:6213649] CoreData: XPC: Unable to load metadata: Error Domain=NSCocoaErrorDomain Code=134070 "An error occurred in the persistent store." UserInfo={Problem=request failed, insufficient permission}
2021-09-17 23:39:24.610959-0700 nextzoom[51558:6213649] [error] error: addPersistentStoreWithType:configuration:URL:options:error: returned error NSCocoaErrorDomain (134070)
CoreData: error: addPersistentStoreWithType:configuration:URL:options:error: returned error NSCocoaErrorDomain (134070)
CoreData: annotation: userInfo:
CoreData: annotation:   Problem : request failed, insufficient permission
CoreData: annotation: storeType: NSXPCStore
CoreData: annotation: configuration: (null)
CoreData: annotation: URL: file:///Users/%%%%%%/Library/Calendars/Calendar%20Cache
CoreData: annotation: options:
CoreData: annotation:   NSMigratePersistentStoresAutomaticallyOption : 1
CoreData: annotation:   agentOrDaemon : 1
CoreData: annotation:   NSInferMappingModelAutomaticallyOption : 1
CoreData: annotation:   serviceName : com.apple.CalendarAgent.database
CoreData: annotation:   NSPersistentHistoryTrackingKey : {
    NSPersistentHistoryTrackingEntitiesToExclude =     (
        ChangeRequest
    );
}
Program ended with exit code: 0

当前问题表现为系统未弹出日历权限申请弹窗,但如果我添加通讯录权限entitlement及Privacy - Contacts Usage Description配置,运行时会正常弹出通讯录访问申请弹窗,应用也会出现在系统安全与隐私设置的通讯录权限列表中,唯独日历权限始终无法正常触发申请流程。


解决方案

1. 补全权限申请逻辑,避免进程提前退出

你当前仅初始化了EKEventStore实例,没有主动触发权限申请流程,同时命令行工具执行完所有同步代码后会直接终止,异步的权限请求还未发出进程就已结束,这是弹窗无法弹出的核心原因。
修复方式:主动调用requestAccess(to:completion:)方法申请权限,同时使用信号量阻塞进程直到权限请求回调返回,示例代码如下:

import Foundation
import EventKit

let store = EKEventStore()
let semaphore = DispatchSemaphore(value: 0)

store.requestAccess(to: .event) { granted, error in
    if let error = error {
        print("权限申请失败: \(error.localizedDescription)")
    } else if granted {
        print("日历权限申请成功")
        // 后续日历操作逻辑可放在此处
    } else {
        print("用户拒绝了日历权限")
    }
    semaphore.signal()
}

semaphore.wait()
exit(0)

2. 校验沙箱权限配置

确认你的.entitlements文件中存在正确的macOS日历权限配置,不要误用iOS平台的权限键:

<key>com.apple.security.personal-information.calendars</key>
<true/>

3. 校验Info.plist配置

确认Info.plist中的日历权限说明键为NSCalendarsUsageDescription,不要出现拼写错误,你已开启的Create Info.plist Section in Binary配置符合命令行工具嵌入Info.plist的要求,无需修改。

缓存清理(可选)

如果修改后依然无法触发弹窗,可先清理旧的权限缓存:

  • 打开系统偏好设置 > 安全与隐私 > 隐私 > 日历,删除列表中对应应用的条目
  • 执行终端命令tccutil reset Calendar清空所有日历权限缓存,之后重新运行项目即可

内容的提问来源于stack exchange,提问作者Simon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:45:03