EventKit en Xamarin.iOS
iOS tiene dos aplicaciones relacionadas con el calendario integradas: la aplicación de calendario y la aplicación de recordatorios. Es lo suficientemente sencillo como para entender cómo la aplicación de calendario administra los datos del calendario, pero la aplicación de recordatorios es menos obvia. Los recordatorios pueden tener fechas asociadas en términos de cuándo deben, cuándo se completan, etc. Por lo tanto, iOS almacena todos los datos del calendario, ya sean eventos de calendario o recordatorios, en una ubicación, denominada Base de datos de calendario.
El marco EventKit proporciona una manera de acceder a los datos calendarios,eventos de calendario y recordatorios que almacena la base de datos de calendario. El acceso a los calendarios y eventos de calendario ha estado disponible desde iOS 4, pero el acceso a los recordatorios es nuevo en iOS 6.
En esta guía se trata lo siguiente:
- Conceptos básicos de EventKit: esto presentará las partes fundamentales de EventKit a través de las clases principales y proporciona una comprensión de su uso. Esta sección es necesaria para leer antes de abordar la siguiente parte del documento.
- Tareas comunes: la sección de tareas comunes está pensada para ser una referencia rápida sobre cómo hacer cosas comunes, como . enumerar calendarios, crear, guardar y recuperar recordatorios y eventos de calendario, así como usar los controladores integrados para crear y modificar eventos de calendario. Esta sección no necesita leerse de forma front-to-back, ya que está pensada para ser una referencia para tareas concretas.
Todas las tareas de esta guía están disponibles en la aplicación de ejemplo complementaria:
Requisitos
EventKit se introdujo en iOS 4.0, pero el acceso a los datos de Reminders se introdujo en iOS 6.0. Por lo tanto, para realizar el desarrollo general de EventKit, deberá tener como destino al menos la versión 4.0 y la 6.0 para los recordatorios.
Además, la aplicación Recordatorios no está disponible en el simulador, lo que significa que los datos de los recordatorios tampoco estarán disponibles, a menos que los agregue primero. Además, las solicitudes de acceso solo se muestran al usuario en el dispositivo real. Por lo tanto, el desarrollo de EventKit se prueba mejor en el dispositivo.
Conceptos básicos del Kit de eventos
Al trabajar con EventKit, es importante tener una idea de las clases comunes y su uso. Todas estas clases se pueden encontrar en EventKit y EventKitUI (para EKEventEditController ).
EventStore
La clase EventStore es la clase más importante de EventKit porque es necesaria para realizar cualquier operación en EventKit. Se puede pensar en como el almacenamiento persistente, o motor de base de datos, para todos los datos de EventKit. Desde tiene acceso a los calendarios y eventos de calendario de la aplicación de calendario, así como a los EventStore recordatorios de la aplicación de recordatorios.
Dado que es como un motor de base de datos, debe ser de larga duración, lo que significa que se debe crear y destruir lo menos posible durante la vigencia de una instancia EventStore de aplicación. De hecho, se recomienda que, una vez que cree una instancia de en una aplicación, mantenga esa referencia durante toda la vigencia de la aplicación, a menos que esté seguro de que no la necesitará de EventStore nuevo. Además, todas las llamadas deben ir a una única EventStore instancia. Por este motivo, se recomienda el patrón Singleton para mantener disponible una única instancia.
Creación de un almacén de eventos
El código siguiente muestra una manera eficaz de crear una única instancia de la clase y hacer que esté disponible estáticamente EventStore desde dentro de una aplicación:
public class App
{
public static App Current {
get { return current; }
}
private static App current;
public EKEventStore EventStore {
get { return eventStore; }
}
protected EKEventStore eventStore;
static App ()
{
current = new App();
}
protected App ()
{
eventStore = new EKEventStore ( );
}
}
El código anterior usa el patrón Singleton para crear una instancia de cuando EventStore se carga la aplicación. A EventStore continuación, se puede acceder a globalmente desde dentro de la aplicación de la siguiente manera:
App.Current.EventStore;
Tenga en cuenta que todos los ejemplos de aquí usan este patrón, por lo que hacen referencia a a EventStore través de App.Current.EventStore .
Solicitud de acceso a los datos de calendario y recordatorio
Antes de que se le permita acceder a cualquier dato a través de EventStore, una aplicación primero debe solicitar acceso a los datos de eventos del calendario o a los datos de recordatorios, en función de cuál necesite. Para facilitar esto, expone un método denominado que, cuando se llama, mostrará una vista de alerta al usuario que le dice que la aplicación solicita acceso a los datos del calendario o a los datos de recordatorio, en función de cuál se le EventStoreRequestAccessEKEntityType pase. Dado que genera una vista de alerta, la llamada es asincrónica y llamará a un controlador de finalización pasado como (o Lambda) a él que recibirá dos parámetros; un booleano de si se concedió acceso o no, y un , que, si no es NULL, contendrá información de NSActionNSError error en la solicitud. Por ejemplo, el código siguiente solicitará acceso a los datos de eventos del calendario y mostrará una vista de alerta si no se concedió la solicitud.
App.Current.EventStore.RequestAccess (EKEntityType.Event,
(bool granted, NSError e) => {
if (granted)
//do something here
else
new UIAlertView ( "Access Denied",
"User Denied Access to Calendar Data", null,
"ok", null).Show ();
} );
Una vez que se haya concedido la solicitud, se recordará siempre que la aplicación esté instalada en el dispositivo y no se mostrará una alerta al usuario. Sin embargo, el acceso solo se concede al tipo de recurso, ya sea eventos de calendario o recordatorios concedidos. Si una aplicación necesita acceso a ambos, debe solicitar ambos.
Dado que se recuerda el permiso, resulta relativamente barato realizar la solicitud cada vez, por lo que es una buena idea solicitar siempre acceso antes de realizar una operación.
Además, dado que se llama al controlador de finalización en un subproceso independiente (que no es de interfaz de usuario), se debe llamar a cualquier actualización de la interfaz de usuario en el controlador de finalización a través de ; de lo contrario, se producirá una excepción y, si no se detecta, la aplicación se InvokeOnMainThread bloqueará.
EKEntityType
EKEntityType es una enumeración que describe el tipo de EventKit elemento o datos. Tiene dos valores: Event y Reminder. Se usa en una serie de métodos, incluido para saber a qué tipo de datos acceder EventStore.RequestAccessEventKit o recuperar.
EKCalendar
EKCalendar representa un calendario, que contiene un grupo de eventos de calendario. Los calendarios se pueden almacenar en muchos lugares diferentes, como localmente, en iCloud,en una ubicación de proveedor de terceros, como un Exchange Server o Google,etc. Muchas veces se usa para saber dónde buscar eventos o dónde guardarlos.
EKEventEditController
EKEventEditController se puede encontrar en el espacio de nombres y es un controlador integrado que se puede usar para editar o crear eventos de calendario. Al igual que los controladores de cámara integrados, realiza el trabajo pesado para mostrar la interfaz de EKEventEditController usuario y controlar el guardado.
EKEvent
EKEvent representa un evento de calendario. Tanto EKEvent como EKReminder heredan de y tienen campos como EKCalendarItem , , y así TitleNotes sucesivamente.
EKReminder
EKReminder representa un elemento de recordatorio.
EKSpan
EKSpan es una enumeración que describe el intervalo de eventos al modificar eventos que pueden repetirse y tiene dos valores: ThisEvent y FutureEvents. ThisEvent significa que los cambios solo se producirán en el evento concreto de la serie a la que se hace referencia, mientras que afectará a ese evento y a todas FutureEvents las periodicidad futuras.
Tareas
Para facilitar el uso, el uso de EventKit se ha dividido en tareas comunes, que se describen en las secciones siguientes.
Enumerar calendarios
Para enumerar los calendarios que el usuario ha configurado en el dispositivo, llame a en y pase el tipo de GetCalendarsEventStore calendarios (recordatorios o eventos) que desea recibir:
EKCalendar[] calendars =
App.Current.EventStore.GetCalendars ( EKEntityType.Event );
Agregar o modificar un evento mediante el controlador integrado
EKEventEditViewController realiza una gran parte del trabajo pesado si desea crear o editar un evento con la misma interfaz de usuario que se presenta al usuario al usar la aplicación de calendario:
Para usarlo, querrá declararlo como una variable de nivel de clase para que no se recolecte como elementos no utilizados si se declara dentro de un método:
public class HomeController : DialogViewController
{
protected CreateEventEditViewDelegate eventControllerDelegate;
...
}
A continuación, para iniciarla, cree una instancia de ella, asíéchale una referencia a , conectarle un delegado EventStoreEventStore y, a continuación, mostrarlo mediante PresentViewController :
EventKitUI.EKEventEditViewController eventController =
new EventKitUI.EKEventEditViewController ();
// set the controller's event store - it needs to know where/how to save the event
eventController.EventStore = App.Current.EventStore;
// wire up a delegate to handle events from the controller
eventControllerDelegate = new CreateEventEditViewDelegate ( eventController );
eventController.EditViewDelegate = eventControllerDelegate;
// show the event controller
PresentViewController ( eventController, true, null );
Opcionalmente, si desea rellenar previamente el evento, puede crear un nuevo evento (como se muestra a continuación) o recuperar un evento guardado:
EKEvent newEvent = EKEvent.FromStore ( App.Current.EventStore );
// set the alarm for 10 minutes from now
newEvent.AddAlarm ( EKAlarm.FromDate ( DateTime.Now.AddMinutes ( 10 ) ) );
// make the event start 20 minutes from now and last 30 minutes
newEvent.StartDate = DateTime.Now.AddMinutes ( 20 );
newEvent.EndDate = DateTime.Now.AddMinutes ( 50 );
newEvent.Title = "Get outside and exercise!";
newEvent.Notes = "This is your reminder to go and exercise for 30 minutes.”;
Si desea rellenar previamente la interfaz de usuario, asegúrese de establecer la propiedad Event en el controlador:
eventController.Event = newEvent;
Para usar un evento existente, consulte la sección Recuperación de un evento por identificador más adelante.
El delegado debe invalidar el Completed método , al que llama el controlador cuando el usuario termina con el cuadro de diálogo:
protected class CreateEventEditViewDelegate : EventKitUI.EKEventEditViewDelegate
{
// we need to keep a reference to the controller so we can dismiss it
protected EventKitUI.EKEventEditViewController eventController;
public CreateEventEditViewDelegate (EventKitUI.EKEventEditViewController eventController)
{
// save our controller reference
this.eventController = eventController;
}
// completed is called when a user eith
public override void Completed (EventKitUI.EKEventEditViewController controller, EKEventEditViewAction action)
{
eventController.DismissViewController (true, null);
}
}
}
Opcionalmente, en el delegado, puede comprobar la acción en el método para modificar el evento y volver a guardar, o hacer otras cosas, si se cancela, etc.
public override void Completed (EventKitUI.EKEventEditViewController controller, EKEventEditViewAction action)
{
eventController.DismissViewController (true, null);
switch ( action ) {
case EKEventEditViewAction.Canceled:
break;
case EKEventEditViewAction.Deleted:
break;
case EKEventEditViewAction.Saved:
// if you wanted to modify the event you could do so here,
// and then save:
//App.Current.EventStore.SaveEvent ( controller.Event, )
break;
}
}
Crear un evento mediante programación
Para crear un evento en el código, use el método de generador FromStore en la clase y establezca los datos en él:
EKEvent newEvent = EKEvent.FromStore ( App.Current.EventStore );
// set the alarm for 10 minutes from now
newEvent.AddAlarm ( EKAlarm.FromDate ( DateTime.Now.AddMinutes ( 10 ) ) );
// make the event start 20 minutes from now and last 30 minutes
newEvent.StartDate = DateTime.Now.AddMinutes ( 20 );
newEvent.EndDate = DateTime.Now.AddMinutes ( 50 );
newEvent.Title = "Get outside and do some exercise!";
newEvent.Notes = "This is your motivational event to go and do 30 minutes of exercise. Super important. Do this.";
Debe establecer el calendario en el que desea guardar el evento, pero si no tiene ninguna preferencia, puede usar el valor predeterminado:
newEvent.Calendar = App.Current.EventStore.DefaultCalendarForNewEvents;
Para guardar el evento, llame al método SaveEvent en :
NSError e;
App.Current.EventStore.SaveEvent ( newEvent, EKSpan.ThisEvent, out e );
Una vez guardado, la propiedad EventIdentifier se actualizará con un identificador único que se puede usar más adelante para recuperar el evento:
Console.WriteLine ("Event Saved, ID: " + newEvent.CalendarItemIdentifier);
EventIdentifier es un GUID con formato de cadena.
Crear un recordatorio mediante programación
La creación de un recordatorio en el código es muy similar a la creación de un evento de calendario:
EKReminder reminder = EKReminder.Create ( App.Current.EventStore );
reminder.Title = "Do something awesome!";
reminder.Calendar = App.Current.EventStore.DefaultCalendarForNewReminders;
Para guardar, llame al método SaveReminder en :
NSError e;
App.Current.EventStore.SaveReminder ( reminder, true, out e );
Recuperar un evento por identificador
Para recuperar un evento por su identificador, use el método EventFromIdentifier en y pásle el que EventIdentifier se extrayó del evento:
EKEvent mySavedEvent = App.Current.EventStore.EventFromIdentifier ( newEvent.EventIdentifier );
Para los eventos, hay otras dos propiedades de identificador, EventIdentifier pero es la única que funciona para esto.
Recuperar un recordatorio por identificador
Para recuperar un recordatorio, use el método GetCalendarItem en y pásle calendarItemIdentifier:
EKCalendarItem myReminder = App.Current.EventStore.GetCalendarItem ( reminder.CalendarItemIdentifier );
Dado que devuelve , se debe convertir a si necesita tener acceso a los datos de GetCalendarItem recordatorio o usar la instancia como un elemento EKCalendarItemEKReminderEKReminder posterior.
No use para eventos de calendario, ya que, en el momento de GetCalendarItem escribir, no funciona.
Eliminación de un evento
Para eliminar un evento de calendario, llame a RemoveEvent en y pase una referencia al evento y el elemento EKSpan adecuado:
NSError e;
App.Current.EventStore.RemoveEvent ( mySavedEvent, EKSpan.ThisEvent, true, out e);
Sin embargo, tenga en cuenta que, una vez eliminado un evento, la referencia del evento será null .
Eliminación de un recordatorio
Para eliminar un recordatorio, llame a RemoveReminder en y pase una referencia al recordatorio:
NSError e;
App.Current.EventStore.RemoveReminder ( myReminder as EKReminder, true, out e);
Tenga en cuenta que en el código anterior hay una conversión a EKReminder , GetCalendarItem porque se usó para recuperarla.
Búsqueda de eventos
Para buscar eventos de calendario, debe crear un objeto NSPredicate a través del método PredicateForEvents en . Es NSPredicate un objeto de datos de consulta que iOS usa para buscar coincidencias:
DateTime startDate = DateTime.Now.AddDays ( -7 );
DateTime endDate = DateTime.Now;
// the third parameter is calendars we want to look in, to use all calendars, we pass null
NSPredicate query = App.Current.EventStore.PredicateForEvents ( startDate, endDate, null );
Una vez que haya creado NSPredicate , use el método NSPredicate en EventStore :
// execute the query
EKCalendarItem[] events = App.Current.EventStore.EventsMatching ( query );
Tenga en cuenta que las consultas son sincrónicas (bloqueo) y pueden tardar mucho tiempo, en función de la consulta, por lo que es posible que desee crear un nuevo subproceso o tarea para hacerlo.
Búsqueda de recordatorios
La búsqueda de recordatorios es similar a los eventos. requiere un predicado, pero la llamada ya es asincrónica, por lo que no es necesario preocuparse por bloquear el subproceso:
// create our NSPredicate which we'll use for the query
NSPredicate query = App.Current.EventStore.PredicateForReminders ( null );
// execute the query
App.Current.EventStore.FetchReminders (
query, ( EKReminder[] items ) => {
// do someting with the items
} );
Resumen
En este documento se proporciona información general sobre las partes importantes del marco EventKit y varias de las tareas más comunes. Sin embargo, el marco EventKit es muy grande y eficaz e incluye características que no se han introducido aquí, como: actualizaciones por lotes, configuración de alarmas, configuración de periodicidad en eventos, registro y escucha de cambios en la base de datos de calendario, configuración de GeoFences y mucho más. Para obtener más información, consulte la Guía de programación de calendarios y recordatorios de Apple.

