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

Posted

技术标签:

【中文标题】以编程方式在 iPhone 日历中添加自定义事件【英文标题】:Programmatically add custom event in the iPhone Calendar 【发布时间】:2010-09-19 18:17:58 【问题描述】:

有没有办法从自定义 App 中将 iCal 事件添加到 iPhone 日历?

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

答案已过时,请考虑删除此【参考方案2】:

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

我可以成功打开 Google 日历活动屏幕 - 但仅限于主桌面版本,并且在 iPhone Safari 上无法正常显示。 Google 移动日历在 Safari 上可以正常显示,但似乎无法使用 API 添加事件。

目前,我看不出有什么好的出路。

【讨论】:

【参考方案3】:

Calendar access is being added in iPhone OS 4.0:

日历访问 应用程序现在可以直接在 带有 Event Kit 的日历应用程序。 创建重复事件,设置开始和结束 时间并将它们分配给任何日历 在设备上。

【讨论】:

【参考方案4】:

您可以使用 OS 4.0 中的 Event Kit 框架来做到这一点。

在窗口左侧的 Groups and Files Navigator 中右键单击 FrameWorks 组。选择“添加”,然后选择“现有框架”,然后选择“EventKit.Framework”。

那么您应该可以使用如下代码添加事件:

#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

【讨论】:

感谢您发布此信息。只是提醒所有阅读本文的人:注意注意内存泄漏。此代码示例中有几个。此外,最佳实践要求您在 saveEvent:span:error 之后检查 'err' 的值并相应地处理。 你知道如何添加重复事件吗?喜欢每周一的活动吗? 以编程方式添加重复事件:查看developer.apple.com/library/ios/#documentation/EventKit/…。另一种选择是使用框架提供的默认视图控制器来添加/编辑事件(例如 Calendar At-A-Glance 应用程序bit.ly/cJq4Bh)。有关此选项,请参阅 developer.apple.com/library/ios/#documentation/EventKitUI/… 要在 XCode 4 中添加框架,请参阅这个 SO 问题:***.com/questions/3352664/… 4.0?不会在 6 内飞行,请参阅上面的答案【参考方案5】:

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

使用Google's API Objective-C Client

  - (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];
                
              ];

【讨论】:

【参考方案6】:

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

【讨论】:

developer.apple.com/library/ios/#documentation/DataManagement/… Tapku图书馆日历能否与日历应用事件同步 我只知道 Tapku 库是一个日历组件控件,它有一个名为 Data source 的选项。因此,编写您从中获取的源的位置取决于您的逻辑......快乐编码:)【参考方案7】:

基于Apple Documentation,这在 iOS 6.0 中有所改变。

1) 您应该通过“requestAccessToEntityType:completion:”请求访问用户的日历并在块内执行事件处理。

2) 您现在需要提交您的事件或将“提交”参数传递给您的保存/删除调用

其他一切都保持不变...

将 EventKit 框架和 #import &lt;EventKit/EventKit.h&gt; 添加到您的代码中。

在我的示例中,我有一个 NSString *savedEventId 实例属性。

添加事件:

    EKEventStore *store = [EKEventStore new];
    [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) 
        if (!granted)  return; 
        EKEvent *event = [EKEvent eventWithEventStore:store];
        event.title = @"Event Title";
        event.startDate = [NSDate date]; //today
        event.endDate = [event.startDate dateByAddingTimeInterval:60*60];  //set 1 hour meeting
        event.calendar = [store defaultCalendarForNewEvents];
        NSError *err = nil;
        [store saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
        self.savedEventId = event.eventIdentifier;  //save the event id if you want to access this later
    ];

删除事件:

    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];
        
    ];

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

Swift 版本

需要导入 EventKit 框架

import EventKit

添加事件

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
    

移除事件

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
        
    

【讨论】:

对我不起作用,一切正常,但日历中没有事件 所有内容都存储在 ekevent 对象中,但不存储在日历中 hlp me @William T:我可以展示日历应用程序的添加事件屏幕(使用 URL 方案)并传递事件的信息,以便当添加事件屏幕出现时,它会预先填充数据。用户只需要按添加事件按钮。在您添加的示例事件中,没有向用户提供任何指示。 如果似乎一切正常但没有出现日历,请检查 Cloud VS Local 日历是否是问题所在。如果您同时使用云日历和本地日历,则云日历可以强制隐藏本地日历。 @ReddyBasha 添加事件时,需要保存 eventIdentifier 并存储以备将来使用。当你去删除它时,你应该使用那个事件 id。【参考方案8】:

Swift 4.0 实现:

通过import EventKit在页面顶部使用导入

然后

@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 !")
            
        
    )

【讨论】:

你能帮我用谷歌日历来解决同样的答案@Dashrath【参考方案9】:

记得将 endDate 设置为创建的事件,这是强制性的。

否则它将失败(几乎无声)并出现以下错误:

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

对我来说完整的工作代码是:

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
];

【讨论】:

还要记住结束日期必须等于或大于开始日期。否则,您将收到另一个错误。【参考方案10】:

Dashrath 答案的 swift 4 更新

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.
    



别忘了添加日历使用权限

【讨论】:

【参考方案11】:

Swift-4.2 中的工作代码

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)

            
        


       )
    


现在我们将获得事件屏幕,您还可以在此处修改设置:

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

    extension viewController: EKEventEditViewDelegate 

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

    

注意:不要忘记将 NSCalendarsUsageDescription 键添加到 info plist。

【讨论】:

以上是关于以编程方式在 iPhone 日历中添加自定义事件的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式设置 iPhone 闹钟?

使用 PhoneGap/jQuery Mobile 以编程方式在 iPhone/Android 日历中添加事件?

如何以编程方式将访客与会者添加到保存时的 GSuite 日历事件

打开自定义创建的 .ics 文件时,Iphone 中 safari 的奇怪行为

使用内置 iOS 日历以编程方式快速创建日历/访问

如何在 iPhone SDK 中使用自定义字体? [复制]