Agregar mediante programación un evento personalizado en el calendario de iPhone


181

¿Hay alguna forma de agregar el evento iCal al Calendario de iPhone desde la aplicación personalizada?

Respuestas:


166

Según la documentación de Apple , esto ha cambiado un poco a partir de iOS 6.0.

1) Debe solicitar acceso al calendario del usuario a través de "requestAccessToEntityType: completar:" y ejecutar el manejo de eventos dentro de un bloque.

2) Debe confirmar su evento ahora o pasar el parámetro "commit" a su llamada de guardar / eliminar

Todo lo demás se queda igual...

Agregue el marco EventKit y #import <EventKit/EventKit.h>su código.

En mi ejemplo, tengo una propiedad de instancia NSString * savedEventId.

Para agregar un evento:

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

Eliminar el evento:

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

Esto agrega eventos a su calendario predeterminado, si tiene varios calendarios, tendrá que averiguar cuál es

Versión rápida

Necesita importar el marco de EventKit

import EventKit

Añadir evento

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
    }
}

Eliminar evento

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
        }
    }
}

66
no funciona para mí, todo funciona sin errores pero no hay eventos en el calendario
Boris Gafurov

Todo se almacena en el objeto ekevent pero no se almacena dentro del calendario hlp me

1
@William T: ¿Puedo presentar la pantalla Agregar Evento de la aplicación Calendario (usando el Esquema de URL) y pasar la información del evento para que cuando aparezca la pantalla Agregar Evento, haya datos previamente completados. El usuario solo necesita presionar el botón Agregar evento. En su evento de ejemplo agregado sin ninguna indicación para el usuario.
Respuesta

1
si todo parece funcionar pero aún no aparece el calendario, verifique si el problema son los calendarios locales de Cloud VS. Si tiene una combinación de Calendarios Cloud y Local, los calendarios Cloud pueden forzar a los calendarios locales a ocultarse.
zonabi

2
@ReddyBasha cuando agrega el evento, debe guardar el eventIdentifier y almacenarlo para usarlo en el futuro. Debe usar esa identificación de evento cuando vaya a eliminarla.
William T.

154

Puede hacerlo utilizando el marco de Event Kit en OS 4.0.

Haga clic derecho en el grupo FrameWorks en el Navegador de grupos y archivos a la izquierda de la ventana. Seleccione 'Agregar' y luego 'FrameWorks existentes' y luego 'EventKit.Framework'.

Entonces debería poder agregar eventos con código como este:

#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

18
Gracias por publicar esto. Solo un recordatorio para todos los que leen esto: tenga cuidado de detectar pérdidas de memoria. Hay un par en este ejemplo de código. Además, las mejores prácticas dictarían que verifique el valor de 'err' después de saveEvent: span: error y maneje las cosas en consecuencia.
David Carney el

¿Sabes cómo agregar un evento de recurrencia? como un evento para todos los lunes?
Jay Vachhani

55
Agregue eventos de recurrencia mediante programación: consulte esto developer.apple.com/library/ios/#documentation/EventKit/… . Otra opción es utilizar los controladores de vista proporcionados por el marco predeterminado para agregar / editar eventos (como la aplicación Calendar At-A-Glance bit.ly/cJq4Bh ). Para esta opción, consulte developer.apple.com/library/ios/#documentation/EventKitUI/…
DenTheMan

Para agregar marcos en XCode 4, vea esta pregunta SO: stackoverflow.com/questions/3352664/…
Nate

1
4.0? no va a volar en 6 ver respuesta anterior
Boris Gafurov

13

Sí, todavía no hay API para esto (2.1). Pero parecía que en WWDC mucha gente ya estaba interesada en la funcionalidad (incluido yo mismo) y la recomendación era ir al sitio a continuación y crear una solicitud de función para esto. Si hay suficiente interés, podrían terminar moviendo el ICal.framework al SDK público.

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


55
la respuesta no está actualizada, considere eliminar esto
Jasper


5

Puede agregar el evento utilizando la API de eventos como Tristan describió y también puede agregar un evento de Google Calendar que aparece en el calendario de iOS.

utilizando el cliente API Objective-C de Google

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

5

Implementación de Swift 4.0:

utilizar importación en la parte superior de la página por import EventKit

luego

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

¿podría ayudarme con el calendario de Google con respecto a la misma respuesta? @Dashrath
Dilip Tiwari

4

Actualización para swift 4 para la respuesta Dashrath

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.
    }


}

tampoco olvides agregar permiso para el uso del calendario imagen para configuración privada


2

Código de trabajo en 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)

            }
        }


       })
    }

}

Ahora obtendremos la pantalla del evento y aquí también puede modificar su configuración:

ingrese la descripción de la imagen aquí

Ahora agregue el método delegado para manejar Cancelar y agregue la acción del botón de evento de la pantalla de eventos:

    extension viewController: EKEventEditViewDelegate {

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

    }
}

Nota: No olvide agregar la clave NSCalendarsUsageDescription en la lista de información.


1

Recuerde configurar endDate para el evento creado, es obligatorio.

De lo contrario, fallará (casi en silencio) con este error:

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

El código de trabajo completo para mí es:

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

1
Y también recuerde que la fecha de finalización debe ser igual o mayor que la fecha de inicio. De lo contrario, obtendrá otro error.
Moody

0

La idea de Google es buena, pero tiene problemas.

Puedo abrir con éxito una pantalla de eventos de calendario de Google, pero solo en la versión de escritorio principal, y no se muestra correctamente en el iPhone Safari. El calendario móvil de Google, que se muestra correctamente en Safari, no parece funcionar con la API para agregar eventos.

Por el momento, no puedo ver una buena salida de este.


0

Simple ... use la biblioteca tapku ... puede buscar esa palabra en Google y usarla ... es de código abierto ... disfrute ... no necesita molestarse con esos códigos ...



Sincronizar calendario se Tapku Biblioteca con eventos de aplicación de calandra
coder1010

Todo lo que sé es que la biblioteca Tapku es un control de componentes de calendario que tiene una opción llamada Fuente de datos. Así que es lógico escribir de dónde proviene esa fuente ... Happy Coding :)
Rajesh_Bangalore
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.