Share via


EventKit in Xamarin.iOS

iOS verfügt über zwei integrierte kalenderbezogene Anwendungen: die Kalenderanwendung und die Erinnerungsanwendung. Die Verwaltung der Kalenderdaten durch die Kalenderanwendung ist leicht zu verstehen, aber die Erinnerungsanwendung ist weniger offensichtlich. Erinnerungen können mit einem Datum versehen werden, wann sie fällig sind, wann sie abgeschlossen sind, usw. Daher speichert iOS alle Kalenderdaten, unabhängig davon, ob es sich um Kalenderereignisse oder Erinnerungen handelt, an einem Ort, der als Kalenderdatenbank bezeichnet wird.

Das EventKit-Framework bietet eine Möglichkeit, auf die Kalender-, Kalenderereignisse- und Erinnerungsdaten zuzugreifen, die die Kalenderdatenbank speichert. Der Zugriff auf die Kalender und Kalenderereignisse ist seit iOS 4 verfügbar, aber der Zugriff auf Erinnerungen ist neu in iOS 6.

In diesem Leitfaden werden wir Folgendes behandeln:

  • EventKit Basics – Dies führt die grundlegenden Teile von EventKit über die hauptklassen ein und bietet ein Verständnis ihrer Nutzung. Dieser Abschnitt ist erforderlich, bevor der nächste Teil des Dokuments behandelt wird.
  • Allgemeine Aufgaben – Der Abschnitt "Allgemeine Aufgaben " soll eine Kurzübersicht darüber sein, wie Allgemeines ausgeführt wird, z. B. das Aufzählen von Kalendern, das Erstellen, Speichern und Abrufen von Kalenderereignissen und Erinnerungen sowie die Verwendung der integrierten Controller zum Erstellen und Ändern von Kalenderereignissen. Dieser Abschnitt muss nicht front-to-back gelesen werden, da er ein Verweis für bestimmte Vorgänge sein soll.

Alle Aufgaben in diesem Leitfaden sind in der Begleitbeispielanwendung verfügbar:

Die Bildschirme der Begleitbeispielanwendung

Anforderungen

EventKit wurde in iOS 4.0 eingeführt, aber der Zugriff auf Erinnerungsdaten wurde in iOS 6.0 eingeführt. Um die allgemeine EventKit-Entwicklung durchzuführen, müssen Sie mindestens Version 4.0 und 6.0 für Erinnerungen verwenden.

Darüber hinaus ist die Reminders-Anwendung nicht im Simulator verfügbar, was bedeutet, dass Erinnerungsdaten auch nicht verfügbar sind, es sei denn, Sie fügen sie zuerst hinzu. Darüber hinaus werden Zugriffsanforderungen nur dem Benutzer auf dem tatsächlichen Gerät angezeigt. Die EventKit-Entwicklung wird daher am besten auf dem Gerät getestet.

Grundlagen des Event Kit

Bei der Arbeit mit EventKit ist es wichtig, die gemeinsamen Klassen und deren Verwendung zu verstehen. Alle diese Klassen finden Sie in den EventKit und EventKitUI (für die EKEventEditController).

EventStore

Die EventStore-Klasse ist die wichtigste Klasse in EventKit, da sie zum Ausführen von Vorgängen in EventKit erforderlich ist. Es kann als beständiger Speicher oder Datenbankmodul für alle EventKit-Daten betrachtet werden. Von EventStore Ihnen haben Zugriff auf die Kalender- und Kalenderereignisse in der Kalenderanwendung sowie Erinnerungen in der Erinnerungsanwendung.

Da EventStore es sich um ein Datenbankmodul handelt, sollte es langlebig sein, d. h., es sollte während der Lebensdauer einer Anwendungsinstanz so wenig wie möglich erstellt und zerstört werden. Tatsächlich wird empfohlen, dass Sie diesen Verweis nach dem Erstellen einer Instanz einer EventStore Anwendung für die gesamte Lebensdauer der Anwendung beibehalten, es sei denn, Sie sind sicher, dass Sie ihn nicht mehr benötigen. darüber hinaus sollten alle Aufrufe zu einer einzelnen EventStore Instanz wechseln. Aus diesem Grund wird das Singleton-Muster empfohlen, um eine einzelne Instanz verfügbar zu halten.

Erstellen eines Ereignisspeichers

Der folgende Code veranschaulicht eine effiziente Methode zum Erstellen einer einzelnen Instanz der EventStore Klasse und stellt sie in einer Anwendung statisch zur Verfügung:

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

Der obige Code verwendet das Singleton-Muster, um eine Instanz der EventStore Anwendung zu instanziieren, wenn die Anwendung geladen wird. Der EventStore Zugriff kann dann global innerhalb der Anwendung wie folgt erfolgen:

App.Current.EventStore;

Beachten Sie, dass alle Beispiele in diesem Beispiel dieses Muster verwenden, sodass sie auf die EventStore Via App.Current.EventStoreverweisen.

Anfordern des Zugriffs auf Kalender- und Erinnerungsdaten

Bevor eine Anwendung über den EventStore auf Daten zugreifen darf, muss eine Anwendung zuerst den Zugriff auf die Kalenderereignisdaten oder Erinnerungsdaten anfordern, je nachdem, welche Daten Sie benötigen. Um dies zu erleichtern, wird eine Methode verfügbar gemacht, die EventStoreRequestAccess wenn aufgerufen – aufgerufen wird, dem Benutzer eine Warnungsansicht anzeigt, die ihnen mitteilt, dass die Anwendung den Zugriff auf die Kalenderdaten oder Erinnerungsdaten anfordert, je nachdem, welche EKEntityType an sie übergeben wird. Da sie eine Warnungsansicht auslöst, ist der Aufruf asynchron und ruft einen Abschlusshandler auf, der als NSAction (oder Lambda) übergeben wird, der zwei Parameter empfängt; ein boolescher Wert, der angibt, ob der Zugriff gewährt wurde, und ein NSError, der, wenn nicht-NULL, Fehlerinformationen in der Anforderung enthält. Der folgende codierte Code fordert beispielsweise den Zugriff auf Kalenderereignisdaten an und zeigt eine Warnungsansicht an, wenn die Anforderung nicht erteilt wurde.

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

Sobald die Anforderung erteilt wurde, wird sie gespeichert, solange die Anwendung auf dem Gerät installiert ist und dem Benutzer keine Warnung angezeigt wird. Der Zugriff wird jedoch nur auf den Typ der Ressource gewährt, entweder Kalenderereignisse oder Erinnerungen. Wenn eine Anwendung Zugriff auf beide benötigt, sollte sie beide anfordern.

Da sich die Berechtigung erinnert, ist es relativ billig, die Anforderung jedes Mal zu stellen. Daher empfiehlt es sich, vor dem Ausführen eines Vorgangs immer den Zugriff anzufordern.

Da der Abschlusshandler für einen separaten Thread (nicht ui) aufgerufen wird, sollten alle Aktualisierungen der Benutzeroberfläche im Abschlusshandler über InvokeOnMainThreadaufgerufen werden, andernfalls wird eine Ausnahme ausgelöst, und wenn sie nicht abgefangen wird, stürzt die Anwendung ab.

EKEntityType

EKEntityType ist eine Aufzählung, die den Typ des Elements oder der EventKit Daten beschreibt. Es hat zwei Werte: Event und Erinnerung. Es wird in einer Reihe von Methoden verwendet, z EventStore.RequestAccess . B. um zu ermitteln EventKit , auf welche Art von Daten sie zugreifen oder abrufen können.

EKCalendar

EKCalendar stellt einen Kalender dar, der eine Gruppe von Kalenderereignissen enthält. Kalender können an vielen verschiedenen Orten gespeichert werden, z. B. lokal, in iCloud, an einem Drittanbieterstandort wie einem Exchange Server oder Google usw. EKCalendar Oft wird verwendet, um zu erfahren EventKit , wo nach Ereignissen gesucht werden soll oder wo sie gespeichert werden sollen.

EKEventEditController

EKEventEditController befindet sich im EventKitUI Namespace und ist ein integrierter Controller, der zum Bearbeiten oder Erstellen von Kalenderereignissen verwendet werden kann. Ähnlich wie bei den integrierten Kameracontrollern EKEventEditController lässt sich dies beim Anzeigen der Benutzeroberfläche und der Handhabung des Speicherns schwer heben.

EKEvent

EKEvent stellt ein Kalenderereignis dar. Beide und EKEventEKReminder erben von EKCalendarItem und haben Felder wie Title, Notes, usw.

EKReminder

EKReminder stellt ein Erinnerungselement dar.

EKSpan

EKSpan ist eine Aufzählung, die die Zeitspanne von Ereignissen beschreibt, wenn Ereignisse geändert werden können, die sich wiederholen können, und hat zwei Werte: ThisEvent und FutureEvents. ThisEvent bedeutet, dass alle Änderungen nur für das bestimmte Ereignis in der Serie auftreten, auf die verwiesen wird, während FutureEvents sie sich auf dieses Ereignis und alle zukünftigen Wiederholungen auswirken wird.

Aufgaben

Um die Benutzerfreundlichkeit zu erleichtern, wurde die EventKit-Verwendung in allgemeine Aufgaben unterteilt, die in den folgenden Abschnitten beschrieben werden.

Aufzählen von Kalendern

Zum Aufzählen der Kalender, die der Benutzer auf dem Gerät konfiguriert hat, rufen Sie GetCalendars den EventStore Kalendertyp (erinnerungen oder Ereignisse) auf, die Sie empfangen möchten, und übergeben Sie folgendes:

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

Hinzufügen oder Ändern eines Ereignisses mithilfe des integrierten Controllers

Der EKEventEditViewController erledigt für Sie eine Große Hebelastung, wenn Sie ein Ereignis mit derselben Benutzeroberfläche erstellen oder bearbeiten möchten, die dem Benutzer bei Verwendung der Kalenderanwendung angezeigt wird:

Die Benutzeroberfläche, die dem Benutzer angezeigt wird, wenn die Kalenderanwendung verwendet wird

Um sie zu verwenden, möchten Sie sie als Variable auf Klassenebene deklarieren, damit sie nicht garbage-collection erhält, wenn sie in einer Methode deklariert wird:

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

Um es zu starten: Instanziieren Sie sie, geben Sie ihm einen Verweis auf , EventStoreverkabeln Sie einen EKEventEditViewDelegate-Delegate mit ihm, und zeigen Sie ihn dann mit 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 );

Optional können Sie, wenn Sie das Ereignis vorab auffüllen möchten, entweder ein völlig neues Ereignis erstellen (wie unten dargestellt), oder Sie können ein gespeichertes Ereignis abrufen:

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

Wenn Sie die Benutzeroberfläche vorab auffüllen möchten, stellen Sie sicher, dass Sie die Ereigniseigenschaft auf dem Controller festlegen:

eventController.Event = newEvent;

Informationen zur Verwendung eines vorhandenen Ereignisses finden Sie im Abschnitt "Abrufen eines Ereignisses nach ID " weiter unten.

Der Delegat sollte die Completed Methode überschreiben, die vom Controller aufgerufen wird, wenn der Benutzer mit dem Dialogfeld fertig ist:

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

Optional können Sie in der Stellvertretung die Aktion in der Completed Methode überprüfen, um das Ereignis zu ändern und das Ereignis erneut zu speichern oder andere Aktionen auszuführen, wenn sie abgebrochen wird usw.

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

Programmgesteuertes Erstellen eines Ereignisses

Verwenden Sie zum Erstellen eines Ereignisses im Code die FromStore-Factorymethode für die EKEvent Klasse, und legen Sie alle darin enthaltenen Daten fest:

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

Sie müssen den Kalender festlegen, in dem das Ereignis gespeichert werden soll. Wenn Sie jedoch keine Einstellung haben, können Sie die Standardeinstellung verwenden:

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

Rufen Sie zum Speichern des Ereignisses die SaveEvent-Methode auf:EventStore

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

Nach dem Speichern wird die EventIdentifier-Eigenschaft mit einem eindeutigen Bezeichner aktualisiert, der später zum Abrufen des Ereignisses verwendet werden kann:

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

EventIdentifier ist eine Zeichenfolge, die als GUID formatiert ist.

Programmgesteuertes Erstellen einer Erinnerung

Das Erstellen einer Erinnerung im Code entspricht wesentlich dem Erstellen eines Kalenderereignisses:

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

Rufen Sie zum Speichern die SaveReminder-Methode auf:EventStore

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

Abrufen eines Ereignisses nach ID

Um ein Ereignis anhand der ID abzurufen, verwenden Sie die EventFromIdentifier-Methode für das EventStore Ereignis, und übergeben Sie es an die EventIdentifier vom Ereignis abgerufene:

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

Für Ereignisse gibt es zwei weitere Bezeichnereigenschaften, ist jedoch EventIdentifier die einzige, die für dieses Ereignis funktioniert.

Abrufen einer Erinnerung nach ID

Verwenden Sie zum Abrufen einer Erinnerung die GetCalendarItem-Methode für das EventStore Objekt und übergeben Sie sie an CalendarItemIdentifier:

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

Da GetCalendarItem ein EKCalendarItemWert zurückgegeben wird, muss er in den Fall umwandeln EKReminder , dass Sie auf Erinnerungsdaten zugreifen oder die Instanz später EKReminder verwenden müssen.

Verwenden GetCalendarItem Sie nicht für Kalenderereignisse, wie zum Zeitpunkt des Schreibens, es funktioniert nicht.

Löschen eines Ereignisses

Um ein Kalenderereignis zu löschen, rufen Sie RemoveEvent auf, EventStore und übergeben Sie einen Verweis auf das Ereignis, und die entsprechenden EKSpan:

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

Beachten Sie jedoch, dass nach dem Löschen eines Ereignisses die Ereignisreferenz lautet null.

Löschen einer Erinnerung

Um eine Erinnerung zu löschen, rufen Sie RemoveReminder auf, EventStore und übergeben Sie einen Verweis auf die Erinnerung:

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

Beachten Sie, dass im obigen Code eine Umwandlung EKRemindererfolgt, da GetCalendarItem sie zum Abrufen verwendet wurde.

Suchen nach Ereignissen

Um nach Kalenderereignissen zu suchen, müssen Sie ein NSPredicate-Objekt über die PredicateForEvents-Methode für die EventStore. Ein NSPredicate Abfragedatenobjekt, das iOS verwendet, um Übereinstimmungen zu finden:

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

Nachdem Sie die NSPredicateDatei erstellt haben, verwenden Sie die EventsMatching-Methode für folgendes EventStore:

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

Beachten Sie, dass Abfragen synchron (Blockieren) sind und je nach Abfrage eine lange Zeit in Anspruch nehmen können, sodass Sie möglicherweise einen neuen Thread oder eine neue Aufgabe ausführen möchten.

Suchen nach Erinnerungen

Die Suche nach Erinnerungen ähnelt Ereignissen; es erfordert ein Prädikat, aber der Aufruf ist bereits asynchron, daher müssen Sie sich keine Gedanken über das Blockieren des Threads machen:

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

Zusammenfassung

Dieses Dokument gab einen Überblick über die wichtigen Teile des EventKit-Frameworks und eine Reihe der am häufigsten verwendeten Aufgaben. Das EventKit-Framework ist jedoch sehr groß und leistungsfähig und umfasst Features, die hier noch nicht eingeführt wurden, z. B. Batchaktualisierungen, Konfigurieren von Alarmen, Konfigurieren von Serienereignissen, Registrieren und Überwachen von Änderungen in der Kalenderdatenbank, Festlegen von GeoFences und mehr. Weitere Informationen finden Sie im Programmierhandbuch für Kalender und Erinnerungen von Apple.