像Sunrise一样修改EventKit中的EKParticipants(与会者)
Modifying EKParticipants (attendees) in EventKit like Sunrise
我的目标是将一些受邀者添加到 EKEvent
。我调查了其他类似的问题,例如 this one, but all say that it is essentially impossible to add EKParticipant
s to an EKEvent
programmatically. I do see that the attendees
property is read-only, but I see other services like Sunrise 在他们的移动应用程序中使用它。
我相信他们正在使用至少部分与 EventKit 集成的系统,因为他们正在从用户的 iCal 应用程序中提取日历。例如,从添加的 Exchange 帐户发送的邀请也由 Exchange 服务明确发送,而不是 Sunrise 自己的邀请(结果是直接将活动发布到 Exchange 或发布到 iCal)。
此限制的任何解决方法都会非常有帮助 - 也许可以调用 Exchange 上的端点给 add/remove 受邀者? EventKit 内部的解决方法?只要不是私人 Apple API,我都非常乐意尝试一下。
谢谢!
我想通了!
从本质上讲,必须进入继承自EKParticipant
的EKAttendee
class。我通过使用 NSClassFromString()
方法创建 class 的通用实例来做到这一点。
有了与会者后,您可以使用 setValue:ForKey:
函数设置属性。
最后,将您的 EKAttendee
实例编译成一个数组,并将其设置为 EKEvent
的 attendees
属性.
我在我的设备上使用 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!");
}
Swift 版本 rebello95 的解决方案。我可以确认它很有魅力!我试过 firstName
和 lastName
属性,但它们似乎根本不重要,所以我将它们排除在示例之外。只有 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
}
我的目标是将一些受邀者添加到 EKEvent
。我调查了其他类似的问题,例如 this one, but all say that it is essentially impossible to add EKParticipant
s to an EKEvent
programmatically. I do see that the attendees
property is read-only, but I see other services like Sunrise 在他们的移动应用程序中使用它。
我相信他们正在使用至少部分与 EventKit 集成的系统,因为他们正在从用户的 iCal 应用程序中提取日历。例如,从添加的 Exchange 帐户发送的邀请也由 Exchange 服务明确发送,而不是 Sunrise 自己的邀请(结果是直接将活动发布到 Exchange 或发布到 iCal)。
此限制的任何解决方法都会非常有帮助 - 也许可以调用 Exchange 上的端点给 add/remove 受邀者? EventKit 内部的解决方法?只要不是私人 Apple API,我都非常乐意尝试一下。
谢谢!
我想通了!
从本质上讲,必须进入继承自EKParticipant
的EKAttendee
class。我通过使用 NSClassFromString()
方法创建 class 的通用实例来做到这一点。
有了与会者后,您可以使用 setValue:ForKey:
函数设置属性。
最后,将您的 EKAttendee
实例编译成一个数组,并将其设置为 EKEvent
的 attendees
属性.
我在我的设备上使用 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!");
}
Swift 版本 rebello95 的解决方案。我可以确认它很有魅力!我试过 firstName
和 lastName
属性,但它们似乎根本不重要,所以我将它们排除在示例之外。只有 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
}