关于ios:以编程方式在iPhone日历中添加自定义事件

Programmatically add custom event in the iPhone Calendar

有没有办法从定制的应用程序将iCal事件添加到iPhone日历中?


根据苹果的文档,从iOS6.0开始,这一点已经发生了一些变化。

1)您应该通过"RequestAccessToEntityType:Completion:"请求访问用户日历,并在块内执行事件处理。

2)您需要立即提交事件或将"commit"参数传递给您的save/remove调用。

其他一切都保持不变…

将eventkit框架和#import 添加到代码中。

在我的示例中,我有一个nsstring*savedeventid实例属性。

要添加事件:

2

删除事件:

1
2
3
4
5
6
7
8
9
    EKEventStore* store = [EKEventStore new];
    [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
        if (!granted) { return; }
        EKEvent* eventToRemove = [store eventWithIdentifier:self.savedEventId];
        if (eventToRemove) {
            NSError* error = nil;
            [store removeEvent:eventToRemove span:EKSpanThisEvent commit:YES error:&error];
        }
    }];

这会将事件添加到您的默认日历中,如果您有多个日历,那么您将发现哪一个是

斯威夫特版本

您需要导入EventKit框架

4

添加事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let store = EKEventStore()
store.requestAccessToEntityType(.Event) {(granted, error) in
    if !granted { return }
    var event = EKEvent(eventStore: store)
    event.title ="Event Title"
    event.startDate = NSDate() //today
    event.endDate = event.startDate.dateByAddingTimeInterval(60*60) //1 hour long meeting
    event.calendar = store.defaultCalendarForNewEvents
    do {
        try store.saveEvent(event, span: .ThisEvent, commit: true)
        self.savedEventId = event.eventIdentifier //save event id to access this particular event later
    } catch {
        // Display error to user
    }
}

移除事件

1
2
3
4
5
6
7
8
9
10
11
12
let store = EKEventStore()
store.requestAccessToEntityType(EKEntityTypeEvent) {(granted, error) in
    if !granted { return }
    let eventToRemove = store.eventWithIdentifier(self.savedEventId)
    if eventToRemove != nil {
        do {
            try store.removeEvent(eventToRemove, span: .ThisEvent, commit: true)
        } catch {
            // Display error to user
        }
    }
}


您可以使用OS 4.0中的事件工具包框架来完成此操作。

右键单击窗口左侧"组和文件导航器"中的"框架"组。选择"添加",然后选择"现有框架",然后选择"eventkit.framework"。

然后您应该能够添加具有如下代码的事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#import"EventTestViewController.h"
#import <EventKit/EventKit.h>

@implementation EventTestViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    EKEventStore *eventStore = [[EKEventStore alloc] init];

    EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
    event.title     = @"EVENT TITLE";

    event.startDate = [[NSDate alloc] init];
    event.endDate   = [[NSDate alloc] initWithTimeInterval:600 sinceDate:event.startDate];

    [event setCalendar:[eventStore defaultCalendarForNewEvents]];
    NSError *err;
    [eventStore saveEvent:event span:EKSpanThisEvent error:&err];      
}

@end


是的,这个(2.1)仍然没有API。但在WWDC,似乎已经有很多人对功能感兴趣(包括我自己),建议您访问下面的站点并为此创建一个功能请求。如果有足够的兴趣,他们可能最终会将ical.framework移动到公共SDK。

https://developer.apple.com/bugreporter/


iPhone OS 4.0中添加了日历访问:

0


Swift 4.0实施:

使用import EventKit在页面顶部导入

然后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@IBAction func addtoCalendarClicked(sender: AnyObject) {

    let eventStore = EKEventStore()

    eventStore.requestAccess( to: EKEntityType.event, completion:{(granted, error) in

        if (granted) && (error == nil) {
            print("granted \(granted)")
            print("error \(error)")

            let event = EKEvent(eventStore: eventStore)

            event.title ="Event Title"
            event.startDate = Date()
            event.endDate = Date()
            event.notes ="Event Details Here"
            event.calendar = eventStore.defaultCalendarForNewEvents

            var event_id =""
            do {
                try eventStore.save(event, span: .thisEvent)
                event_id = event.eventIdentifier
            }
            catch let error as NSError {
                print("json error: \(error.localizedDescription)")
            }

            if(event_id !=""){
                print("event added !")
            }
        }
    })
}


您可以使用Tristan概述的事件API添加事件,也可以添加显示在iOS日历中的Google日历事件。

使用谷歌的API Objective-C客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  - (void)addAnEvent {
  // Make a new event, and show it to the user to edit
  GTLCalendarEvent *newEvent = [GTLCalendarEvent object];
  newEvent.summary = @"Sample Added Event";
  newEvent.descriptionProperty = @"Description of sample added event";

  // We'll set the start time to now, and the end time to an hour from now,
  // with a reminder 10 minutes before
  NSDate *anHourFromNow = [NSDate dateWithTimeIntervalSinceNow:60*60];
  GTLDateTime *startDateTime = [GTLDateTime dateTimeWithDate:[NSDate date]
                                                    timeZone:[NSTimeZone systemTimeZone]];
  GTLDateTime *endDateTime = [GTLDateTime dateTimeWithDate:anHourFromNow
                                                  timeZone:[NSTimeZone systemTimeZone]];

  newEvent.start = [GTLCalendarEventDateTime object];
  newEvent.start.dateTime = startDateTime;

  newEvent.end = [GTLCalendarEventDateTime object];
  newEvent.end.dateTime = endDateTime;

  GTLCalendarEventReminder *reminder = [GTLCalendarEventReminder object];
  reminder.minutes = [NSNumber numberWithInteger:10];
  reminder.method = @"email";

  newEvent.reminders = [GTLCalendarEventReminders object];
  newEvent.reminders.overrides = [NSArray arrayWithObject:reminder];
  newEvent.reminders.useDefault = [NSNumber numberWithBool:NO];

  // Display the event edit dialog
  EditEventWindowController *controller = [[[EditEventWindowController alloc] init] autorelease];
  [controller runModalForWindow:[self window]
                          event:newEvent
              completionHandler:^(NSInteger returnCode, GTLCalendarEvent *event) {
                // Callback
                if (returnCode == NSOKButton) {
                  [self addEvent:event];
                }
              }];
}


dashrath答案的swift 4更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import UIKit
import EventKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let eventStore = EKEventStore()

        eventStore.requestAccess( to: EKEntityType.event, completion:{(granted, error) in

            if (granted) && (error == nil) {


                let event = EKEvent(eventStore: eventStore)

                event.title ="My Event"
                event.startDate = Date(timeIntervalSinceNow: TimeInterval())
                event.endDate = Date(timeIntervalSinceNow: TimeInterval())
                event.notes ="Yeah!!!"
                event.calendar = eventStore.defaultCalendarForNewEvents

                var event_id =""
                do{
                    try eventStore.save(event, span: .thisEvent)
                    event_id = event.eventIdentifier
                }
                catch let error as NSError {
                    print("json error: \(error.localizedDescription)")
                }

                if(event_id !=""){
                    print("event added !")
                }
            }
        })
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

也不要忘记添加日历使用权限image for privary setting


SWIFT-4.2中的工作代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import UIKit
import EventKit
import EventKitUI

class yourViewController: UIViewController{

    let eventStore = EKEventStore()

    func addEventToCalendar() {

    eventStore.requestAccess( to: EKEntityType.event, completion:{(granted, error) in
        DispatchQueue.main.async {
            if (granted) && (error == nil) {
                let event = EKEvent(eventStore: self.eventStore)
                event.title = self.headerDescription
                event.startDate = self.parse(self.requestDetails.value(forKey:"session_time") as? String ??"")
                event.endDate = self.parse(self.requestDetails.value(forKey:"session_end_time") as? String ??"")
                let eventController = EKEventEditViewController()
                eventController.event = event
                eventController.eventStore = self.eventStore
                eventController.editViewDelegate = self
                self.present(eventController, animated: true, completion: nil)

            }
        }


       })
    }

}

现在我们将看到事件屏幕,您还可以在这里修改设置:

enter image description here

现在添加委托方法来处理取消并添加事件屏幕的事件按钮操作:

1
2
3
4
5
6
7
    extension viewController: EKEventEditViewDelegate {

    func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
        controller.dismiss(animated: true, completion: nil)

    }
}

注意:不要忘记在信息列表中添加nscalendarsusagedescription键。


记住,要将结束日期设置为已创建事件,它是必需的。

否则,它将失败(几乎是无声的),并出现此错误:

1
"Error Domain=EKErrorDomain Code=3"No end date has been set." UserInfo={NSLocalizedDescription=No end date has been set.}"

我的完整工作代码是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
EKEventStore *store = [EKEventStore new];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
    if (!granted) { return; }
    EKEvent *calendarEvent = [EKEvent eventWithEventStore:store];
    calendarEvent.title = [NSString stringWithFormat:@"CEmprendedor: %@", _event.name];
    calendarEvent.startDate = _event.date;
    // 5 hours of duration, we must add the duration of the event to the API
    NSDate *endDate = [_event.date dateByAddingTimeInterval:60*60*5];
    calendarEvent.endDate = endDate;
    calendarEvent.calendar = [store defaultCalendarForNewEvents];
    NSError *err = nil;
    [store saveEvent:calendarEvent span:EKSpanThisEvent commit:YES error:&err];
    self.savedEventId = calendarEvent.eventIdentifier;  //saving the calendar event id to possibly deleted them
}];


简单…使用Tapku库…你可以用谷歌搜索这个词并使用它…它的开源…享受…不需要窃听那些代码……


谷歌的想法不错,但也有问题。

我可以成功地打开一个谷歌日历事件屏幕-但只在主桌面版本上,它不能在iPhone Safari上正确显示。谷歌移动日历(google mobile calendar)确实在Safari上显示得很好,但似乎无法与API一起添加事件。

目前,我看不出有什么好办法可以摆脱这个困境。