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

Swift开发:EKEvent的occurrenceDate与birthdayContactIdentifier问题求助

嘿,这两个问题我刚好有经验,来帮你捋清楚!

1. 通过birthdayContactIdentifier关联到对应联系人

要拿到这个标识符对应的联系人,你需要用到Contacts框架,步骤如下:

首先记得在项目里导入Contacts模块:

import Contacts

然后核心是用CNContactStore来查询联系人,不过必须先申请权限(否则会崩溃或拿不到数据):

let store = CNContactStore()

// 请求联系人权限
store.requestAccess(for: .contacts) { granted, error in
    guard granted else {
        // 权限被拒绝,这里可以加提示用户开启权限的逻辑
        return
    }
    
    // 权限通过后开始查询
    if let contactId = get_event.birthdayContactIdentifier {
        // 指定需要获取的联系人属性,按需添加即可
        let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactPhoneNumbersKey] as [CNKeyDescriptor]
        do {
            let contact = try store.unifiedContact(withIdentifier: contactId, keysToFetch: keysToFetch)
            // 成功拿到联系人,这里可以做你需要的处理
            print("联系人姓名:\(contact.givenName) \(contact.familyName)")
        } catch {
            print("查询联系人失败:\(error.localizedDescription)")
        }
    }
}

注意:unifiedContact(withIdentifier:keysToFetch:)会返回苹果自动合并后的联系人(如果用户有重复的联系人条目),这是官方推荐的查询方式。另外必须指定要获取的属性,不能传空数组,否则会报错。

2. 解决occurrenceDate的时间显示问题与获取重复频率

关于occurrenceDate的时间偏差

你看到的2020-05-30 02:00:00 +0000是UTC标准时间,而你设置的是本地时间20:00-22:30,两者的差异完全是时区导致的。只需要把UTC时间转换成设备本地时区的时间即可:

if let occurrenceDate = get_event.occurrenceDate {
    // 转换成当前设备的本地时区
    let localDate = occurrenceDate.convert(to: TimeZone.current)
    print("本地时间:\(localDate.description)")
    
    // 如果需要更友好的格式化显示,用DateFormatter
    let formatter = DateFormatter()
    formatter.dateStyle = .full
    formatter.timeStyle = .full
    formatter.timeZone = TimeZone.current
    print("格式化后的本地时间:\(formatter.string(from: localDate))")
}

另外你提到输出了两个时间,建议检查下代码是否误把startDate和occurrenceDate一起打印了——occurrenceDate本身是单个重复实例的开始时间,正常只会输出一个时间。

获取重复频率与规则

要拿到事件的重复信息,直接看EKEvent的recurrenceRule属性,它包含了重复的频率、间隔、结束条件等关键信息:

if let recurrenceRule = get_event.recurrenceRule {
    // 判断重复频率
    switch recurrenceRule.frequency {
    case .daily:
        print("每天重复")
    case .weekly:
        print("每周重复")
    case .monthly:
        print("每月重复")
    case .yearly:
        print("每年重复")
    @unknown default:
        print("未知重复频率")
    }
    
    // 重复间隔:比如间隔1是每周1次,间隔2是每两周1次
    print("重复间隔:\(recurrenceRule.interval)")
    
    // 如果有重复结束日期,可以获取
    if let endDate = recurrenceRule.endDate {
        print("重复结束日期:\(endDate)")
    }
    
    // 每周重复的话,还能拿到具体周几重复(1=周日,2=周一…7=周六)
    if recurrenceRule.frequency == .weekly {
        print("每周重复的星期:\(recurrenceRule.weekdays)")
    }
}

补充:重复事件的startDate和endDate是第一个实例的时间,而occurrenceDate是当前你获取的这个重复实例的时间,两者可能不同哦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 20:52:26