Xamarin.iOS의 EventKit

iOS에는 일정 관련 애플리케이션과 미리 알림 애플리케이션의 두 가지 일정 관련 애플리케이션이 기본 제공됩니다. 일정 애플리케이션이 일정 데이터를 관리하는 방법을 이해할 수 있을 만큼 간단하지만 미리 알림 애플리케이션은 명확하지 않습니다. 미리 알림은 실제로 기한, 완료 시기 등의 측면에서 날짜와 연결된 날짜를 가질 수 있습니다. 따라서 iOS는 일정 이벤트든 미리 알림이든 관계없이 모든 일정 데이터를 일정 데이터베이스라고 하는 한 위치에 저장합니다.

EventKit 프레임워크는 일정 데이터베이스가 저장하는 일정, 일정 이벤트미리 알림 데이터에 액세스하는 방법을 제공합니다. 일정 및 일정 이벤트에 대한 액세스는 iOS 4부터 사용할 수 있지만, 미리 알림에 대한 액세스는 iOS 6의 새로운 기능입니다.

이 가이드에서는 다음을 다룹니다.

  • EventKit 기본 사항 – 주요 클래스를 통해 EventKit의 기본 부분을 소개하고 해당 사용에 대한 이해를 제공합니다. 이 섹션은 문서의 다음 부분을 다루기 전에 읽어야 합니다.
  • 일반 작업 – 일반적인 작업 섹션은 일정 열거, 일정 이벤트 및 미리 알림 만들기, 저장 및 검색, 일정 이벤트 만들기 및 수정을 위한 기본 제공 컨트롤러 사용과 같은 일반적인 작업을 수행하는 방법에 대한 빠른 참조를 위한 것입니다. 이 섹션은 특정 작업에 대한 참조이기 때문에 전면에서 뒤로 읽을 필요가 없습니다.

이 가이드의 모든 작업은 도우미 샘플 애플리케이션에서 사용할 수 있습니다.

The companion sample application screens

요구 사항

EventKit은 iOS 4.0에서 도입되었지만 Reminders 데이터에 대한 액세스는 iOS 6.0에서 도입되었습니다. 따라서 일반적인 EventKit 개발을 수행하려면 미리 알림을 위해 버전 4.0 및 6.0 이상을 대상으로 지정해야 합니다.

또한 미리 알림 애플리케이션은 시뮬레이터에서 사용할 수 없습니다. 즉, 미리 알림 데이터를 먼저 추가하지 않는 한 미리 알림 데이터도 사용할 수 없습니다. 또한 액세스 요청은 실제 디바이스에서 사용자에게만 표시됩니다. 따라서 EventKit 개발은 디바이스에서 가장 잘 테스트됩니다.

Event Kit 기본 사항

EventKit을 사용할 때는 공통 클래스 및 해당 사용량을 파악하는 것이 중요합니다. 이러한 클래스는 모두 및 (의 경우EKEventEditController)에서 EventKitEventKitUI 찾을 수 있습니다.

EventStore

EventStore 클래스는 EventKit에서 모든 작업을 수행해야 하므로 EventKit에서 가장 중요한 클래스입니다. 모든 EventKit 데이터에 대해 영구 스토리지 또는 데이터베이스 엔진으로 간주할 수 있습니다. EventStore 사용자는 일정 애플리케이션의 일정 및 일정 이벤트와 미리 알림 애플리케이션의 미리 알림에 모두 액세스할 수 있습니다.

EventStore 데이터베이스 엔진과 같으므로 수명이 길어야 하므로 애플리케이션 인스턴스의 수명 동안 가능한 한 적게 만들고 제거해야 합니다. 실제로 애플리케이션에서 하나의 인스턴스를 EventStore 만든 후에는 다시 필요하지 않은 한 애플리케이션의 전체 수명 동안 해당 참조를 유지하는 것이 좋습니다. 또한 모든 호출은 단일 EventStore 인스턴스로 이동해야 합니다. 이러한 이유로 단일 인스턴스를 사용 가능한 상태로 유지하는 데 싱글톤 패턴을 사용하는 것이 좋습니다.

이벤트 저장소 만들기

다음 코드는 클래스의 EventStore 단일 인스턴스를 만들고 애플리케이션 내에서 정적으로 사용할 수 있도록 하는 효율적인 방법을 보여 줍니다.

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

위의 코드는 Singleton 패턴을 사용하여 애플리케이션이 로드되는 경우의 EventStore 인스턴스를 인스턴스화합니다. EventStore 그런 다음 다음과 같이 애플리케이션 내에서 전역적으로 액세스할 수 있습니다.

App.Current.EventStore;

여기에 있는 모든 예제는 이 패턴을 사용하므로 을 통해 App.Current.EventStore참조합니다EventStore.

일정 및 미리 알림 데이터에 대한 액세스 요청

EventStore를 통해 데이터에 액세스하도록 허용하기 전에 애플리케이션은 먼저 필요한 데이터에 따라 일정 이벤트 데이터 또는 미리 알림 데이터에 대한 액세스를 요청해야 합니다. 이를 EventStore 용이하게 하기 위해 호출 RequestAccess 될 때 호출된 메서드를 노출하면 애플리케이션이 전달되는 데이터에 따라 EKEntityType 애플리케이션이 일정 데이터 또는 미리 알림 데이터에 대한 액세스를 요청하고 있음을 알리는 경고 보기가 사용자에게 표시됩니다. 경고 보기가 발생하므로 호출은 비동기적이며, 두 개의 매개 변수를 수신하는 완료 처리기(또는 람다)로 전달되는 NSAction 완료 처리기를 호출합니다. 이는 액세스가 부여되었는지 여부의 부울이고 NSError, null이 아닌 경우 요청에 오류 정보가 포함됩니다. 예를 들어 다음 코드는 일정 이벤트 데이터에 대한 액세스를 요청하고 요청이 부여되지 않은 경우 경고 보기를 표시합니다.

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

요청이 부여되면 애플리케이션이 디바이스에 설치되고 사용자에게 경고가 표시되지 않는 한 기억됩니다. 그러나 액세스 권한은 일정 이벤트 또는 부여된 미리 알림과 같은 리소스 유형에만 부여됩니다. 애플리케이션이 둘 다에 액세스해야 하는 경우 둘 다 요청해야 합니다.

사용 권한이 기억되므로 매번 요청을 수행하는 것이 비교적 저렴하므로 작업을 수행하기 전에 항상 액세스를 요청하는 것이 좋습니다.

또한 완료 처리기가 별도의(비 UI) 스레드에서 호출되기 때문에 완료 처리기의 UI에 대한 모든 업데이트를 통해 InvokeOnMainThread호출해야 합니다. 그렇지 않으면 예외가 throw되고, catch되지 않으면 애플리케이션이 충돌합니다.

EKEntityType

EKEntityType 는 항목 또는 데이터의 형식 EventKit 을 설명하는 열거형입니다. 두 가지 값이 Event 있습니다. 미리 알림입니다. 액세스하거나 검색할 데이터의 종류를 알려주 EventKit 는 등 다양한 메서드 EventStore.RequestAccess 에 사용됩니다.

EKCalendar

EKCalendar 는 일정 이벤트 그룹을 포함하는 달력을 나타냅니다. 일정은 로컬, iCloud, Exchange Server 또는 Google과 같은 타사 공급자 위치 등 다양한 위치에 저장할 수 있습니다. 이벤트를 찾을 위치 또는 저장할 위치를 지정 EventKit 하는 데 여러 번 EKCalendar 사용됩니다.

EKEventEditController

EKEventEditController 는 네임스페이스에서 EventKitUI 찾을 수 있으며 일정 이벤트를 편집하거나 만드는 데 사용할 수 있는 기본 제공 컨트롤러입니다. 기본 제공 카메라 컨트롤러와 EKEventEditController 마찬가지로 UI를 표시하고 저장을 처리하는 데 많은 작업을 수행합니다.

EKEvent

EKEvent 는 달력 이벤트를 나타냅니다. 둘 다 EKEvent 상속 EKCalendarItem 되며 EKReminder , Notes등과 같은 Title필드가 있습니다.

EKReminder

EKReminder 는 미리 알림 항목을 나타냅니다.

EKSpan

EKSpan 은 되풀이될 수 있는 이벤트를 수정할 때 이벤트 범위를 설명하는 열거형이며 두 값이 있습니다. ThisEventFutureEvents. ThisEvent 는 참조되는 계열의 특정 이벤트에만 변경이 발생하는 반면 FutureEvents 해당 이벤트와 이후의 모든 되풀이에 영향을 줍니다.

작업

사용 편의성을 위해 EventKit 사용은 다음 섹션에 설명된 일반적인 작업으로 분할되었습니다.

일정 열거

사용자가 디바이스에서 구성한 일정을 열거하려면 수신하려는 일정 유형(미리 알림 또는 이벤트)을 호출 GetCalendarsEventStore 하고 전달합니다.

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

기본 제공 컨트롤러를 사용하여 이벤트 추가 또는 수정

일정 애플리케이션을 사용할 때 사용자에게 표시되는 것과 동일한 UI를 사용하여 이벤트를 만들거나 편집하려는 경우 EKEventEditViewController는 많은 작업을 수행합니다.

The UI that is presented to the user when using the Calendar Application

이를 사용하려면 메서드 내에서 선언된 경우 가비지 수집되지 않도록 클래스 수준 변수로 선언해야 합니다.

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

그런 다음, 인스턴스화하고, 참조를 EventStore제공하고, EKEventEditViewDelegate 대리자를 연결한 다음, 다음을 사용하여 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 );

필요에 따라 이벤트를 미리 채웁히려면 아래와 같이 새 이벤트를 만들거나 저장된 이벤트를 검색할 수 있습니다.

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

UI를 미리 채우려면 컨트롤러에서 이벤트 속성을 설정해야 합니다.

eventController.Event = newEvent;

기존 이벤트를 사용하려면 나중에 ID이벤트 검색 섹션을 참조하세요.

대리자는 사용자가 대화 상자를 완료할 때 컨트롤러에서 호출하는 메서드를 재정 Completed 의해야 합니다.

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

필요에 따라 대리자에서 메서드의 Completed Action을 검사 이벤트를 수정하고 다시 저장하거나 취소된 경우 다른 작업을 수행할 수 있습니다.

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

프로그래밍 방식으로 이벤트 만들기

코드에서 이벤트를 만들려면 클래스에서 FromStore 팩터리 메서드를 EKEvent 사용하고 해당 클래스에 대한 데이터를 설정합니다.

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

이벤트를 저장할 일정을 설정해야 하지만 기본 설정이 없는 경우 기본값을 사용할 수 있습니다.

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

이벤트를 저장하려면 다음에서 SaveEvent 메서드를 호출합니다 EventStore.

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

저장 되면 EventIdentifier 속성은 나중에 이벤트를 검색하는 데 사용할 수 있는 고유 식별자를 사용하여 업데이트됩니다.

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

EventIdentifier 은 문자열 형식의 GUID입니다.

프로그래밍 방식으로 미리 알림 만들기

코드에서 미리 알림을 만드는 것은 일정 이벤트를 만드는 것과 거의 동일합니다.

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

저장하려면 다음에서 SaveReminder 메서드를 호출합니다 EventStore.

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

ID로 이벤트 검색

ID로 이벤트를 검색하려면 EventFromIdentifier 메서드를 EventStore 사용하여 이벤트에서 끌어온 이벤트를 전달 EventIdentifier 합니다.

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

이벤트의 경우 두 개의 다른 식별자 속성이 있지만 EventIdentifier 이 속성에 대해 작동하는 유일한 식별자 속성입니다.

ID로 미리 알림 검색

미리 알림을 검색하려면 GetCalendarItem 메서드를 EventStore 사용하여 CalendarItemIdentifier에 전달합니다.

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

반환 GetCalendarItem 되므로 EKCalendarItem미리 알림 데이터에 액세스하거나 인스턴스 EKReminderEKReminder 나중에 사용해야 하는 경우 캐스팅해야 합니다.

작성 시처럼 일정 이벤트에는 사용하지 GetCalendarItem 마세요.

이벤트 삭제

일정 이벤트를 삭제하려면 사용자에 대해 RemoveEventEventStore 호출하고 이벤트에 대한 참조와 적절한 EKSpan참조를 전달합니다.

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

그러나 이벤트가 삭제된 후에는 이벤트 참조가 됩니다 null.

미리 알림 삭제

미리 알림을 삭제하려면 RemoveReminderEventStore 호출하고 미리 알림에 대한 참조를 전달합니다.

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

위의 코드에는 캐스트가 있습니다. 이는 캐스트를 EKReminder검색하는 데 사용되었기 때문 GetCalendarItem 입니다.

이벤트 검색

일정 이벤트를 검색하려면 .의 PredicateForEvents 메서드EventStore통해 NSPredicate 개체를 만들어야 합니다. iOS NSPredicate 에서 일치 항목을 찾는 데 사용하는 쿼리 데이터 개체입니다.

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

만든 NSPredicate후에는 다음에서 EventsMatching 메서드를 EventStore사용합니다.

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

쿼리는 동기(차단)이며 쿼리에 따라 시간이 오래 걸릴 수 있으므로 새 스레드 또는 작업을 실행하여 수행할 수 있습니다.

미리 알림 검색

미리 알림을 검색하는 것은 이벤트와 비슷합니다. 조건자가 필요하지만 호출은 이미 비동기이므로 스레드 차단에 대해 걱정할 필요가 없습니다.

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

요약

이 문서에서는 EventKit 프레임워크의 중요한 부분과 가장 일반적인 여러 작업에 대해 간략하게 설명했습니다. 그러나 EventKit 프레임워크는 매우 크고 강력하며 일괄 처리 업데이트, 경보 구성, 이벤트에 대한 되풀이 구성, 일정 데이터베이스의 변경 내용 등록 및 수신 대기, GeoFences 설정 등에서 도입되지 않은 기능을 포함합니다. 자세한 내용은 Apple의 일정 및 미리 알림 프로그래밍 가이드를 참조하세요.