像日出一样修改EventKit中的EKParticipants(参与者)

24
我的目标是将一些被邀请人添加到一个 EKEvent 中。我查看了其他类似的问题,例如像这个问题,但是所有的答案都说基本上无法通过编程方式添加 EKParticipantEKEvent 中。我看到 attendees 属性是只读的,但是我看到其他服务,如 Sunrise 在他们的移动应用程序中使用它。
我有信心他们使用的是至少部分与 EventKit 集成的系统,因为他们从用户的 iCal 应用中拉取日历。例如从添加的 Exchange 帐户发送的邀请明显也是由 Exchange 服务发送的,而不是 Sunrise 自己的邀请(这是直接发布事件到 Exchange 或发布到 iCal 的结果)。
任何绕过此限制的方法都将非常有帮助,也许是在 Exchange 上可以调用的端点来添加/删除被邀请人?在 EventKit 内部的解决方法?只要不是私有的 Apple API,我将非常乐意尝试它。
谢谢!

从我的经验来看,即使使用私有API,也无法添加EKParticipant对象。保存总是失败的。可能是因为我没有深入挖掘,但我的感觉是他们只希望人们使用EventKitUI添加参与者(也许是出于隐私原因)。如果像Sunrise这样的流行应用程序使用私有API来编辑事件,我会感到惊讶。 - Léo Natan
@LeoNatan 感谢您的回复。不幸的是,我必须遵守App Store指南,使用公共API。是否有任何方法可以通过使用从EventKit获取的日历ID进行REST调用后添加参与者? - rebello95
不完全是。EK标识符通常是设备特定的,而不是远程服务器(Exchange、iCloud等)的真实标识符。 - Léo Natan
@LeoNatan 嗯,说得好。我只是想不到他们还有其他的方式... - rebello95
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - rebello95
显示剩余4条评论
2个回答

17

我搞定了!

基本上,你必须进入EKAttendee类,它继承自EKParticipant。我通过使用NSClassFromString()方法创建该类的通用实例来实现这一点。

一旦你有一个与会者,就可以使用setValue:ForKey:函数设置属性。

最后,将您的EKAttendee实例编译成数组,并将其设置为EKEventattendees属性。

我在我的设备上使用Exchange帐户进行了测试,它完美地工作-邀请已发送!

下面的代码是我现在用于设置事件参与者的代码。我的示例是用于创建新事件的,但是对于现有事件,可以通过复制EKEvent上的attendees列表,然后修改并重新设置它来轻松完成。

//Create generic event info
EKEvent *event = [EKEvent eventWithEventStore:database];
event.title = @"TEST EVENT";
event.location = @"Test location";
event.notes = @"Example notes";
event.startDate = [NSDate date];
event.endDate = [[NSDate date] dateByAddingTimeInterval:(60 * 60)];
event.calendar = exchange;

//Do our super clever hack
NSMutableArray *attendees = [NSMutableArray new];
for (int i = 0; i < 5; i++) {

    //Initialize a EKAttendee object, which is not accessible and inherits from EKParticipant
    Class className = NSClassFromString(@"EKAttendee");
    id attendee = [className new];

    //Set the properties of this attendee using setValue:forKey:
    [attendee setValue:@"Invitee" forKey:@"firstName"];
    [attendee setValue:[NSString stringWithFormat:@"#%i", i + 1] forKey:@"lastName"];
    [attendee setValue:@"test@email.com" forKey:@"emailAddress"];

    //Add this attendee to a list so we can assign it to the event
    [attendees addObject:attendee];
}

//Finally, add the invitees to the event
[event setValue:attendees forKey:@"attendees"];

//Save the event!
NSError *error = nil;
[database saveEvent:event span:EKSpanThisEvent error:&error];
if (error) {
    NSLog(@"Save failed with error: %@", error);
} else {
    NSLog(@"Success!");
}

@LeoNatan 嗯,我已经在真实设备上进行了测试,还没有遇到问题。猜我们拭目以待吧... - rebello95
@LeoNatan 你过去遇到过这方面的什么问题吗? - Ewan Mellor
4
我已经使用了上述方法。但是在使用iCal日历时,我遇到了以下错误。保存失败并显示以下错误信息:Error Domain=EKErrorDomain Code=31 "Attendees cannot be changed" UserInfo=0x7f85a06d5880 {NSLocalizedDescription=Attendees cannot be changed}请问该怎样处理?请有人帮我解决这个问题。 - Neela
1
@AndrewNester 我曾经使用这种方法成功地通过了应用程序审核,没有任何问题。 - rebello95
1
@rebello95 感谢您的快速回复!解决方案有效,我将尝试提交到应用商店,看看效果如何。再次感谢! - Andrew Nester
显示剩余8条评论

10

这是rebello95的解决方案的Swift版本。我可以确认它非常有效!我尝试了firstNamelastName属性,但它们似乎并不重要,所以我在我的示例中省略了它们。只有emailAddress很重要,它与您的联系人列表匹配,以在例如本机日历应用程序中显示全名。

private func createEventWithAttendees() {
    let eventStore = EKEventStore()

    let calendars = eventStore.calendarsForEntityType(.Event)

    let event = EKEvent(eventStore: eventStore)
    event.title = "TEST EVENT"
    event.startDate = NSDate()
    event.endDate = NSDate().dateByAddingTimeInterval(60 * 60)
    event.calendar = calendars[0]

    var attendees = [EKParticipant]()
    for i in 0 ..< 5 {
        if let attendee = createParticipant(email: "test\(i)@email.com") {
            attendees.append(attendee)
        }
    }
    event.setValue(attendees, forKey: "attendees")

    try! eventStore.saveEvent(event, span: .ThisEvent)
}

private func createParticipant(email email: String) -> EKParticipant? {
    let clazz: AnyClass? = NSClassFromString("EKAttendee")
    if let type = clazz as? NSObject.Type {
        let attendee = type.init()
        attendee.setValue(email, forKey: "emailAddress")
        return attendee as? EKParticipant
    }
    return nil
}

尝试在Swift 3.1和iOS 10.x上运行此代码 - eventStore.saveEvent(...)会失败,并显示错误消息Error Domain = EKErrorDomain Code = 35“无法更改参与者。” - leviathan
(在 Xcode 9.1 beta 和 iPhone X 模拟器上测试过)我能够邀请人并作为组织者进行附加(对现有数组进行更改),但无法作为受邀者进行附加。此外,我无法接受邀请。在所有失败的情况中,错误信息是“无法更改参与者”。有任何帮助吗? - Harry Ng
谢谢...不要在模拟器中尝试。它在模拟器中无法工作....但在设备上对我有效。 - Deepti Raghav
这很棒,除了现有的邀请。如何接受邀请?当我尝试保存更改时,我也会收到“无法更改与会者”的消息,就像@HarryNg一样。 - Burgler-dev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接