EventKit dans Xamarin.iOS

iOS intègre deux applications liées au calendrier : l’application calendrier et l’application rappels. Il est assez simple de comprendre comment l’application calendrier gère les données de calendrier, mais l’application Rappels est moins évidente. Les rappels peuvent en fait avoir des dates associées en termes de date d’échéance, de fin d’exécution, etc. Par conséquent, iOS stocke toutes les données de calendrier, qu’il s’agisse d’événements de calendrier ou de rappels, dans un emplacement appelé base de données du calendrier.

L’infrastructure EventKit permet d’accéder aux données calendriers, événements de calendrier et rappels que la base de données calendrier stocke. L’accès aux calendriers et aux événements de calendrier est disponible depuis iOS 4, mais l’accès aux rappels est nouveau dans iOS 6.

Dans ce guide, nous allons aborder les points suivants :

  • Notions de base d’EventKit : cela présente les éléments fondamentaux d’EventKit via les classes principales et fournit une compréhension de leur utilisation. Cette section doit être lue avant d’aborder la partie suivante du document.
  • Tâches courantes : la section Tâches courantes est destinée à être une référence rapide sur la façon d’effectuer des tâches courantes telles que : énumération de calendriers, création, enregistrement et récupération d’événements de calendrier et de rappels, ainsi que l’utilisation des contrôleurs intégrés pour créer et modifier des événements de calendrier. Cette section n’a pas besoin d’être lue de front à dos, car elle est destinée à être une référence pour des tâches particulières.

Toutes les tâches de ce guide sont disponibles dans l’exemple d’application complémentaire :

Les exemples d’écrans d’application complémentaires

Spécifications

EventKit a été introduit dans iOS 4.0, mais l’accès aux données rappels a été introduit dans iOS 6.0. Par conséquent, pour effectuer un développement EventKit général, vous devez cibler au moins la version 4.0 et la version 6.0 pour les rappels.

En outre, l’application Rappels n’est pas disponible sur le simulateur, ce qui signifie que les données des rappels ne seront pas non plus disponibles, sauf si vous les ajoutez d’abord. En outre, les demandes d’accès s’affichent uniquement à l’utilisateur sur l’appareil réel. Par conséquent, il est préférable de tester le développement EventKit sur l’appareil.

Concepts de base du Kit d’événements

Lorsque vous utilisez EventKit, il est important de bien comprendre les classes courantes et leur utilisation. Toutes ces classes se trouvent dans et EventKitEventKitUI (pour ).EKEventEditController

EventStore

La classe EventStore est la classe la plus importante dans EventKit, car elle est nécessaire pour effectuer des opérations dans EventKit. Il peut être considéré comme le stockage persistant, ou moteur de base de données, pour toutes les données EventKit. À partir de EventStore vous avez accès aux calendriers et aux événements de calendrier dans l’application calendrier, ainsi qu’aux rappels dans l’application Rappels.

Comme EventStore il s’agit d’un moteur de base de données, il doit être de longue durée, ce qui signifie qu’il doit être créé et détruit le moins possible pendant la durée de vie d’une application instance. En fait, il est instance EventStore recommandé de conserver cette référence pendant toute la durée de vie de l’application, sauf si vous êtes sûr de ne plus en avoir besoin. en outre, tous les appels doivent être passés à un seul EventStore instance. Pour cette raison, le modèle Singleton est recommandé pour conserver une seule instance disponible.

Création d’un magasin d’événements

Le code suivant illustre un moyen efficace de créer une seule instance de la classe et de la EventStore rendre disponible de manière statique à partir d’une application :

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

Le code ci-dessus utilise le modèle Singleton pour instancier un instance du lors du chargement de EventStore l’application. Le EventStore est ensuite accessible globalement à partir de l’application comme suit :

App.Current.EventStore;

Notez que tous les exemples ici utilisent ce modèle. Ils font donc référence à via EventStoreApp.Current.EventStore.

Demande d’accès aux données de calendrier et de rappel

Avant d’être autorisée à accéder à des données via EventStore, une application doit d’abord demander l’accès aux données d’événements de calendrier ou aux données de rappel, en fonction de celle dont vous avez besoin. Pour faciliter cela, le EventStore expose une méthode appelée RequestAccess qui, lorsqu’elle est appelée, affiche une vue d’alerte à l’utilisateur qui lui indique que l’application demande l’accès aux données de calendrier ou aux données de rappel, selon ce qui EKEntityType lui est passé. Étant donné qu’il déclenche une vue d’alerte, l’appel est asynchrone et appelle un gestionnaire d’achèvement NSAction passé en tant que (ou Lambda) à celui-ci qui recevra deux paramètres : un booléen indiquant si l’accès a été accordé ou non, et un NSError, qui, s’il n’est pas null, contiendra des informations d’erreur dans la demande. Par exemple, le code suivant demande l’accès aux données d’événement de calendrier et affiche une vue d’alerte si la demande n’a pas été accordée.

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

Une fois la demande accordée, elle est mémorisée tant que l’application est installée sur l’appareil et n’affiche pas d’alerte à l’utilisateur. Toutefois, l’accès est accordé uniquement au type de ressource, qu’il s’agisse d’événements de calendrier ou de rappels accordés. Si une application a besoin d’accéder aux deux, elle doit demander les deux.

Étant donné que l’autorisation est mémorisée, il est relativement peu coûteux d’effectuer la demande à chaque fois. Il est donc judicieux de toujours demander l’accès avant d’effectuer une opération.

En outre, étant donné que le gestionnaire d’achèvement est appelé sur un thread distinct (hors interface utilisateur), toutes les mises à jour de l’interface utilisateur dans le gestionnaire de saisie semi-automatique doivent être appelées via InvokeOnMainThread, sinon une exception est levée et, si elle n’est pas interceptée, l’application se bloque.

EKEntityType

EKEntityType est une énumération qui décrit le type d’élément ou de EventKit données. Il a deux valeurs : Event et Rappel. Il est utilisé dans un certain nombre de méthodes, notamment EventStore.RequestAccess pour déterminer EventKit le type de données à accéder ou à récupérer.

EKCalendar

EKCalendar représente un calendrier, qui contient un groupe d’événements de calendrier. Les calendriers peuvent être stockés dans de nombreux endroits différents, tels que localement, dans iCloud, dans un emplacement de fournisseur tiers comme un Exchange Server ou Google, etc. EKCalendar Souvent, est utilisé pour indiquer EventKit où rechercher des événements ou où les enregistrer.

EKEventEditController

EKEventEditController se trouve dans l’espace EventKitUI de noms et est un contrôleur intégré qui peut être utilisé pour modifier ou créer des événements de calendrier. Tout comme les contrôleurs de caméra intégrés, EKEventEditController fait le gros travail pour vous en affichant l’interface utilisateur et en gérant l’enregistrement.

EKEvent

EKEvent représente un événement de calendrier. EKReminder Et EKEvent héritent de EKCalendarItem et ont des champs tels que Title, Notes, et ainsi de suite.

EKReminder

EKReminder représente un élément de rappel.

EKSpan

EKSpan est une énumération qui décrit l’étendue des événements lors de la modification d’événements qui peuvent se reproduire, et a deux valeurs : ThisEvent et FutureEvents. ThisEvent signifie que les modifications ne se produisent que pour l’événement particulier de la série référencée, alors que FutureEvents cela affecte cet événement et toutes les périodicités futures.

Tâches

Pour faciliter l’utilisation, l’utilisation d’EventKit a été divisée en tâches courantes, décrites dans les sections suivantes.

Énumérer les calendriers

Pour énumérer les calendriers que l’utilisateur a configurés sur l’appareil, appelez GetCalendars sur et EventStore transmettez le type de calendriers (rappels ou événements) que vous souhaitez recevoir :

EKCalendar[] calendars = 
App.Current.EventStore.GetCalendars ( EKEntityType.Event );

Ajouter ou modifier un événement à l’aide du contrôleur intégré

EKEventEditViewController effectue une grande partie du travail difficile pour vous si vous souhaitez créer ou modifier un événement avec la même interface utilisateur que celle présentée à l’utilisateur lors de l’utilisation de l’application Calendrier :

Interface utilisateur présentée à l’utilisateur lors de l’utilisation de l’application Calendrier

Pour l’utiliser, vous devez le déclarer en tant que variable de niveau classe afin qu’il ne soit pas ramassé par le garbage-collect s’il est déclaré dans une méthode :

public class HomeController : DialogViewController
{
        protected CreateEventEditViewDelegate eventControllerDelegate;
        ...
}

Ensuite, pour le lancer : instanciez-le, donnez-lui une référence au , connectez-y EventStoreun délégué EKEventEditViewDelegate , puis affichez-le à l’aide PresentViewControllerde :

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

Si vous souhaitez préremplir l’événement, vous pouvez créer un tout nouvel événement (comme indiqué ci-dessous) ou récupérer un événement enregistré :

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 vous souhaitez préremplir l’interface utilisateur, veillez à définir la propriété Event sur le contrôleur :

eventController.Event = newEvent;

Pour utiliser un événement existant, consultez la section Récupérer un événement par ID plus loin.

Le délégué doit remplacer la Completed méthode, qui est appelée par le contrôleur lorsque l’utilisateur a terminé la boîte de dialogue :

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

Si vous le souhaitez, dans le délégué, vous pouvez case activée l’action dans la Completed méthode pour modifier l’événement et réinscrire, ou effectuer d’autres opérations, si elle est annulée, 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;
        }
}

Création d’un événement par programmation

Pour créer un événement dans le code, utilisez la méthode de fabrique FromStore sur la EKEvent classe et définissez les données de celle-ci :

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.";

Vous devez définir le calendrier dans lequel vous souhaitez enregistrer l’événement, mais si vous n’avez aucune préférence, vous pouvez utiliser la valeur par défaut :

newEvent.Calendar = App.Current.EventStore.DefaultCalendarForNewEvents;

Pour enregistrer l’événement, appelez la méthode SaveEvent sur :EventStore

NSError e;
App.Current.EventStore.SaveEvent ( newEvent, EKSpan.ThisEvent, out e );

Une fois enregistrée, la propriété EventIdentifier est mise à jour avec un identificateur unique qui peut être utilisé ultérieurement pour récupérer l’événement :

Console.WriteLine ("Event Saved, ID: " + newEvent.CalendarItemIdentifier);

EventIdentifier est un GUID au format chaîne.

Créer un rappel par programmation

La création d’un rappel dans le code est pratiquement identique à la création d’un événement de calendrier :

EKReminder reminder = EKReminder.Create ( App.Current.EventStore );
reminder.Title = "Do something awesome!";
reminder.Calendar = App.Current.EventStore.DefaultCalendarForNewReminders;

Pour enregistrer, appelez la méthode SaveReminder sur :EventStore

NSError e;
App.Current.EventStore.SaveReminder ( reminder, true, out e );

Récupération d’un événement par ID

Pour récupérer un événement par son ID, utilisez la méthode EventFromIdentifier sur le et transmettez-lui EventStore le EventIdentifier qui a été extrait de l’événement :

EKEvent mySavedEvent = App.Current.EventStore.EventFromIdentifier ( newEvent.EventIdentifier );

Pour les événements, il existe deux autres propriétés d’identificateur, mais EventIdentifier est la seule qui fonctionne pour cela.

Récupération d’un rappel par ID

Pour récupérer un rappel, utilisez la méthode GetCalendarItem sur le EventStore et transmettez-lui le CalendarItemIdentifier :

EKCalendarItem myReminder = App.Current.EventStore.GetCalendarItem ( reminder.CalendarItemIdentifier );

Étant donné que retourne un EKCalendarItem, il doit être converti EKReminder en si vous devez accéder aux données de rappel ou utiliser le instance ultérieurementEKReminder.GetCalendarItem

N’utilisez pas pour les GetCalendarItem événements de calendrier, car au moment de la rédaction, cela ne fonctionne pas.

Suppression d’un événement

Pour supprimer un événement de calendrier, appelez RemoveEvent sur votre EventStore et transmettez une référence à l’événement et au approprié EKSpan:

NSError e;
App.Current.EventStore.RemoveEvent ( mySavedEvent, EKSpan.ThisEvent, true, out e);

Notez toutefois qu’une fois qu’un événement a été supprimé, la référence d’événement est null.

Suppression d’un rappel

Pour supprimer un rappel, appelez RemoveReminder sur le EventStore et transmettez une référence au rappel :

NSError e;
App.Current.EventStore.RemoveReminder ( myReminder as EKReminder, true, out e);

Notez que dans le code ci-dessus, il y a un cast en EKReminder, car GetCalendarItem a été utilisé pour le récupérer

Recherche d’événements

Pour rechercher des événements de calendrier, vous devez créer un objet NSPredicate via la méthode PredicateForEvents sur le EventStore. Un NSPredicate est un objet de données de requête utilisé par iOS pour localiser les correspondances :

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

Une fois que vous avez créé le NSPredicate, utilisez la méthode EventsMatching sur :EventStore

// execute the query
EKCalendarItem[] events = App.Current.EventStore.EventsMatching ( query );

Notez que les requêtes sont synchrones (bloquantes) et peuvent prendre beaucoup de temps, en fonction de la requête. Vous pouvez donc lancer un nouveau thread ou une nouvelle tâche pour le faire.

Recherche de rappels

La recherche de rappels est similaire aux événements ; il nécessite un prédicat, mais l’appel est déjà asynchrone. Vous n’avez donc pas à vous soucier du blocage du thread :

// 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
        } );

Résumé

Ce document a donné une vue d’ensemble des éléments importants de l’infrastructure EventKit et d’un certain nombre de tâches les plus courantes. Toutefois, l’infrastructure EventKit est très grande et puissante, et inclut des fonctionnalités qui n’ont pas été introduites ici, telles que les mises à jour par lots, la configuration des alarmes, la configuration de la périodicité sur les événements, l’inscription et l’écoute des modifications dans la base de données de calendrier, la définition de GeoFences et bien plus encore. Pour plus d’informations, consultez le Guide de programmation du calendrier et des rappels d’Apple.