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

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

【问题讨论】:

    标签: ios iphone calendar eventkit


    【解决方案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
        

        【讨论】:

        【解决方案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库....你可以谷歌这个词并使用它...它的开源......享受......不需要那些代码的窃听......

          【讨论】:

          【解决方案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。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-12-02
              • 2017-09-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多