Condividi tramite


EventKit in Xamarin.iOS

iOS include due applicazioni correlate al calendario predefinite: l'applicazione calendario e l'applicazione Reminders. È abbastanza semplice capire come l'applicazione calendario gestisce i dati del calendario, ma l'applicazione Promemoria è meno ovvia. I promemoria possono effettivamente avere date associate a loro in termini di quando sono scaduti, al termine, ecc. Di conseguenza, iOS archivia tutti i dati del calendario, ad esempio eventi del calendario o promemoria, in un'unica posizione, denominato Database del calendario.

Il framework EventKit consente di accedere ai dati calendari, eventi del calendario e promemoria archiviati dal database del calendario. L'accesso ai calendari e agli eventi del calendario è disponibile a partire da iOS 4, ma l'accesso ai promemoria è nuovo in iOS 6.

In questa guida verrà illustrato quanto segue:

  • Nozioni di base di EventKit: introduce i componenti fondamentali di EventKit tramite le classi principali e fornisce una comprensione dell'utilizzo. Questa sezione è necessaria prima di affrontare la parte successiva del documento.
  • Attività comuni: la sezione attività comuni è destinata a essere un riferimento rapido su come eseguire operazioni comuni, ad esempio l'enumerazione di calendari, la creazione, il salvataggio e il recupero di eventi e promemoria del calendario, nonché l'uso dei controller predefiniti per la creazione e la modifica di eventi del calendario. Questa sezione non deve essere letta front-to-back, perché è destinata a essere un riferimento per determinate attività.

Tutte le attività in questa guida sono disponibili nell'applicazione di esempio complementare:

Schermate dell'applicazione di esempio complementare

Requisiti

EventKit è stato introdotto in iOS 4.0, ma l'accesso ai dati dei promemoria è stato introdotto in iOS 6.0. Di conseguenza, per eseguire lo sviluppo generale di EventKit, è necessario specificare come destinazione almeno la versione 4.0 e la versione 6.0 per i promemoria.

Inoltre, l'applicazione Reminders non è disponibile nel simulatore, il che significa che anche i dati dei promemoria non saranno disponibili, a meno che non vengano aggiunti per primi. Inoltre, le richieste di accesso vengono visualizzate solo all'utente nel dispositivo effettivo. Di conseguenza, lo sviluppo di EventKit è stato testato al meglio nel dispositivo.

Nozioni di base su Event Kit

Quando si usa EventKit, è importante avere una conoscenza delle classi comuni e del relativo utilizzo. Tutte queste classi sono disponibili in EventKit e EventKitUI (per ).EKEventEditController

EventStore

La classe EventStore è la classe più importante in EventKit perché è necessaria per eseguire qualsiasi operazione in EventKit. Può essere considerato come l'archiviazione permanente o il motore di database per tutti i dati EventKit. Dall'utente EventStore è possibile accedere sia ai calendari che agli eventi del calendario nell'applicazione calendario, nonché ai promemoria nell'applicazione Promemoria.

Poiché EventStore è come un motore di database, deve essere di lunga durata, vale a dire che deve essere creato e eliminato il minor possibile durante la durata di un'istanza dell'applicazione. In effetti, è consigliabile creare un'istanza di EventStore in un'applicazione, mantenere tale riferimento per l'intera durata dell'applicazione, a meno che non si sia certi di non averlo più necessario. inoltre, tutte le chiamate devono passare a una singola EventStore istanza. Per questo motivo, il modello Singleton è consigliato per mantenere disponibile una singola istanza.

Creazione di un archivio eventi

Il codice seguente illustra un modo efficiente per creare una singola istanza della EventStore classe e renderla disponibile in modo statico dall'interno di un'applicazione:

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

Il codice precedente usa il modello Singleton per creare un'istanza di EventStore quando l'applicazione viene caricata. È EventStore quindi possibile accedere a livello globale dall'interno dell'applicazione come indicato di seguito:

App.Current.EventStore;

Si noti che tutti gli esempi in qui usano questo modello, in modo che facciano riferimento a EventStore tramite App.Current.EventStore.

Richiesta di accesso ai dati del calendario e del promemoria

Prima di poter accedere a tutti i dati tramite EventStore, un'applicazione deve prima richiedere l'accesso ai dati degli eventi del calendario o ai promemoria, a seconda di quale sia necessario. Per facilitare questo problema, espone EventStore un metodo denominato che, quando viene chiamato RequestAccess , visualizzerà una visualizzazione degli avvisi all'utente che informa che l'applicazione richiede l'accesso ai dati del calendario o ai dati del promemoria, a seconda del quale EKEntityType viene passato. Poiché genera una visualizzazione avviso, la chiamata è asincrona e chiamerà un gestore di completamento passato come NSAction (o Lambda) a esso che riceverà due parametri, un valore booleano che indica se è stato concesso o meno l'accesso e un oggetto NSError, che, se non Null conterrà informazioni sull'errore nella richiesta. Ad esempio, il codice seguente richiederà l'accesso ai dati dell'evento del calendario e mostrerà una visualizzazione avviso se la richiesta non è stata concessa.

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 volta concessa, la richiesta verrà memorizzata finché l'applicazione è installata nel dispositivo e non verrà visualizzato un avviso per l'utente. Tuttavia, l'accesso viene concesso solo al tipo di risorsa, ovvero gli eventi del calendario o i promemoria concessi. Se un'applicazione deve accedere a entrambi, deve richiedere entrambi.

Poiché l'autorizzazione viene memorizzata, è relativamente economico effettuare ogni volta la richiesta, quindi è consigliabile richiedere sempre l'accesso prima di eseguire un'operazione.

Inoltre, poiché il gestore di completamento viene chiamato su un thread separato (non dell'interfaccia utente), tutti gli aggiornamenti all'interfaccia utente nel gestore di completamento devono essere chiamati tramite InvokeOnMainThread, altrimenti verrà generata un'eccezione e, se non rilevata, l'applicazione si arresterà in modo anomalo.

EKEntityType

EKEntityType è un'enumerazione che descrive il tipo di EventKit elemento o dati. Ha due valori: Event e Reminder. Viene usato in diversi metodi, tra cui EventStore.RequestAccess per indicare EventKit il tipo di dati a cui accedere o recuperare.

EKCalendar

EKCalendar rappresenta un calendario che contiene un gruppo di eventi del calendario. I calendari possono essere archiviati in molti luoghi diversi, ad esempio localmente, in iCloud, in una posizione del provider di terze parti, ad esempio Exchange Server o Google e così via. Molte volte EKCalendar viene usato per indicare EventKit dove cercare gli eventi o dove salvarli.

EKEventEditController

EKEventEditController è disponibile nello EventKitUI spazio dei nomi ed è un controller predefinito che può essere usato per modificare o creare eventi del calendario. Proprio come i controller della fotocamera incorporati, EKEventEditController esegue il pesante sollevamento per te nella visualizzazione dell'interfaccia utente e nella gestione del salvataggio.

EKEvent

EKEvent rappresenta un evento di calendario. Sia EKEvent che EKReminder ereditano da EKCalendarItem e hanno campi come Title, Notese così via.

EKReminder

EKReminder rappresenta un elemento di promemoria.

EKSpan

EKSpan è un'enumerazione che descrive l'intervallo di eventi durante la modifica di eventi che possono verificarsi e ha due valori: ThisEvent e FutureEvents. ThisEvent significa che tutte le modifiche verranno apportate solo all'evento specifico nella serie a cui viene fatto riferimento, mentre FutureEvents influirà sull'evento e su tutte le ricorrenze future.

Attività

Per semplificare l'uso, l'utilizzo di EventKit è stato suddiviso in attività comuni, descritte nelle sezioni seguenti.

Enumerare calendari

Per enumerare i calendari configurati dall'utente nel dispositivo, chiamare GetCalendars su EventStore e passare il tipo di calendari (promemoria o eventi) da ricevere:

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

Aggiungere o modificare un evento usando il controller predefinito

EKEventEditViewController esegue molte operazioni complesse se vuoi creare o modificare un evento con la stessa interfaccia utente presentata all'utente quando usi l'applicazione Calendario:

Interfaccia utente presentata all'utente quando si usa l'applicazione calendario

Per usarlo, è necessario dichiararlo come variabile a livello di classe in modo che non venga sottoposto a Garbage Collection se viene dichiarato all'interno di un metodo:

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

Quindi, per avviarlo: crearne un'istanza, assegnargli un riferimento a EventStore, collegare un delegato EKEventEditViewDelegate a esso e quindi visualizzarlo usando 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 );

Facoltativamente, se si vuole precompilare l'evento, è possibile creare un nuovo evento (come illustrato di seguito) oppure recuperare un evento salvato:

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

Se si vuole precompilare l'interfaccia utente, assicurarsi di impostare la proprietà Event nel controller:

eventController.Event = newEvent;

Per usare un evento esistente, vedere la sezione Recuperare un evento in base all'ID più avanti.

Il delegato deve eseguire l'override del Completed metodo , che viene chiamato dal controller al termine della finestra di dialogo:

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

Facoltativamente, nel delegato è possibile controllare l'azione nel Completed metodo per modificare l'evento e ricampionare o eseguire altre operazioni, se viene annullata, e così via:

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

Creazione di un evento a livello di codice

Per creare un evento nel codice, usare il metodo factory FromStore nella EKEvent classe e impostare tutti i dati su di esso:

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

È necessario impostare il calendario in cui si desidera salvare l'evento, ma se non si ha alcuna preferenza, è possibile usare il valore predefinito:

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

Per salvare l'evento, chiamare il metodo SaveEvent in EventStore:

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

Dopo il salvataggio, la proprietà EventIdentifier verrà aggiornata con un identificatore univoco che può essere usato in un secondo momento per recuperare l'evento:

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

EventIdentifier è un GUID formattato in formato stringa.

Creare un promemoria a livello di codice

La creazione di un promemoria nel codice equivale alla creazione di un evento di calendario:

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

Per salvare, chiamare il metodo SaveReminder in EventStore:

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

Recupero di un evento in base all'ID

Per recuperare un evento in base all'ID, usare il metodo EventFromIdentifier sull'oggetto EventStore e passarlo all'oggetto EventIdentifier estratto dall'evento:

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

Per gli eventi, sono presenti due altre proprietà dell'identificatore, ma EventIdentifier è l'unica che funziona per questo.

Recupero di un promemoria in base all'ID

Per recuperare un promemoria, utilizzare il metodo GetCalendarItem su EventStore e passarlo a CalendarItemIdentifier:

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

Poiché GetCalendarItem restituisce un EKCalendarItemoggetto , deve essere eseguito il cast a EKReminder se è necessario accedere ai dati del promemoria o usare l'istanza come un EKReminder secondo momento.

Non usare GetCalendarItem per gli eventi del calendario, come al momento della scrittura, non funziona.

Eliminazione di un evento

Per eliminare un evento del calendario, chiamare RemoveEvent sull'oggetto EventStore e passare un riferimento all'evento e l'oggetto appropriato EKSpan:

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

Si noti tuttavia che, dopo l'eliminazione di un evento, il riferimento all'evento sarà null.

Eliminazione di un promemoria

Per eliminare un promemoria, chiama RemoveReminder su EventStore e passa un riferimento al promemoria:

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

Si noti che nel codice precedente è presente un cast a EKReminder, perché GetCalendarItem è stato usato per recuperarlo

Ricerca di eventi

Per cercare gli eventi del calendario, è necessario creare un oggetto NSPredicate tramite il metodo PredicateForEvents in .EventStore È NSPredicate un oggetto dati di query usato da iOS per individuare le corrispondenze:

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

Dopo aver creato , NSPredicateusare il metodo EventsMatching in EventStore:

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

Si noti che le query sono sincrone (blocco) e potrebbero richiedere molto tempo, a seconda della query, quindi è consigliabile avviare un nuovo thread o un'attività per eseguirla.

Ricerca di promemoria

La ricerca di promemoria è simile agli eventi; richiede un predicato, ma la chiamata è già asincrona, quindi non è necessario preoccuparsi di bloccare il 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
        } );

Riepilogo

Questo documento ha fornito una panoramica dei componenti importanti del framework EventKit e di una serie di attività più comuni. Tuttavia, il framework EventKit è molto grande e potente e include funzionalità che non sono state introdotte qui, ad esempio: aggiornamenti in batch, configurazione degli avvisi, configurazione della ricorrenza in eventi, registrazione e ascolto delle modifiche nel database del calendario, impostazione di GeoFences e altro ancora. Per altre informazioni, vedere Calendario e promemoria di Apple.