天天看點

iOS開發之EventKit架構的應用(一)

一、關于系統月曆和提醒事宜

     iOS系統自帶的Calendar應用非常強大,使用者可以在其中添加日程事件,并且其提供了接口供其他應用進行調用,可以向月曆中進行事件的讀取和寫入。

     首先,Canlendar應用預設建立了幾個類型的月曆,使用者也可以根據需要建立自定義的月曆,如下圖:

iOS開發之EventKit架構的應用(一)

在上圖中,US Holidays、Birthdays、Siri Found in Apps和Calendar是預設建立的幾個月曆,Custom是自定義的月曆,當使用者建立月曆事件時,需要關聯到某個月曆,如下:

iOS開發之EventKit架構的應用(一)

對于系統的Reminders,其主要作用是提供事件清單,使用者可以向事件清單中添加提醒事件,同樣,提供預設建立了兩個事件清單,使用者也可以根據需要自行建立新的事件清單,如下圖:

iOS開發之EventKit架構的應用(一)

使用月曆和提醒事宜這兩個應用,可以提高生活工作效率,例如郵件應用通過與月曆的互動可以将會議郵件添加到使用者的日程中,EventKit架構則是提供了接口與這兩個應用進行互動。

二、EventKit架構概覽

   EventKit核心的用途是配合系統的月曆與提醒應用,對事件提醒進行管理,其中核心類即結構如下:

iOS開發之EventKit架構的應用(一)

從圖中可以看出,重要資料的管理類為EKEventStore,其他類都是用來描述對應的資料,下面會一一介紹。

三、月曆事件操作

     第三方應用需要操作使用者的月曆事件,需要擷取使用者授權,首先需要在info.plist檔案中添加如下權限請求字段:

iOS開發之EventKit架構的應用(一)

擷取目前Calendars應用中定義的月曆示例代碼如下:

#import "ViewController.h"

#import <EventKit/EventKit.h>

@interface ViewController ()

@property (nonatomic, strong) EKEventStore *eventStore;

@end

@implementation ViewController

- (void)viewDidLoad {

   [super viewDidLoad];

   // 初始化

   self.eventStore = [[EKEventStore alloc] init];

   // 請求權限

   [self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {

       if (!granted) {

           NSLog(@"拒絕通路");

       } else {

           // 擷取所有月曆

           NSArray *calendars = [self.eventStore calendarsForEntityType:EKEntityTypeEvent];

           for (EKCalendar *calendar in calendars) {

               NSLog(@"%@", calendar);

           }

       }

   }];

}

上面方法會擷取到所有的月曆,也可以通過來源來擷取月曆,後面會具體介紹。

使用如下代碼可以添加新的月曆,通常,第三方應用如果要向使用者月曆中添加事件,可以先添加一個新的月曆:

- (void)createNewCalendar {

   EKCalendar *calendar = [EKCalendar calendarForEntityType:EKEntityTypeEvent eventStore:self.eventStore];

   for (EKSource *source in self.eventStore.sources) {

       if (source.sourceType == EKSourceTypeLocal) {

           // 設定來源為本地

           calendar.source = source;

   }

   calendar.title = @"珲少的事項月曆";//自定義月曆标題

   calendar.CGColor = [UIColor purpleColor].CGColor;//自定義月曆顔色

   NSError* error;

   [_eventStore saveCalendar:calendar commit:YES error:&error];

效果如下圖:

iOS開發之EventKit架構的應用(一)

月曆事件的查詢需要構造NSPredicate對象,示例如下:

- (void)queryEvent {

   for (EKCalendar *cal in [self.eventStore calendarsForEntityType:EKEntityTypeEvent]) {

       if ([cal.title isEqualToString:@"珲少的事項月曆"]) {

           NSCalendar *calendar = [NSCalendar currentCalendar];

           NSDateComponents *oneMonthFromNowComponents = [[NSDateComponents alloc] init];

           oneMonthFromNowComponents.month = 1;

           NSDate *oneMonthFromNow = [calendar dateByAddingComponents:oneMonthFromNowComponents

                                                               toDate:[NSDate date]

                                                              options:0];

           // 擷取從今往後一個月的

           NSPredicate*predicate = [self.eventStore predicateForEventsWithStartDate:[NSDate date] endDate:oneMonthFromNow calendars:@[cal]];

           NSArray *eventArray = [self.eventStore eventsMatchingPredicate:predicate];

           NSLog(@"%@", eventArray);

通過存儲的相關接口,也可以對某個事件進行修改,或建立新的事件,示例如下:

- (void)createEvent {

   EKCalendar *calen = nil;

           calen = cal;

   EKEvent *event = [EKEvent eventWithEventStore:self.eventStore];

   event.title = @"從應用建立的事件";

   event.startDate = [NSDate date];

   event.calendar = calen;

   NSCalendar *calendar = [NSCalendar currentCalendar];

   NSDateComponents *oneMonthFromNowComponents = [[NSDateComponents alloc] init];

   oneMonthFromNowComponents.hour += 1;

   NSDate *endDate = [calendar dateByAddingComponents:oneMonthFromNowComponents

                                                       toDate:[NSDate date]

                                                      options:0];

   event.endDate = endDate;

   event.notes = @"備注";

   [event setAllDay:NO];//設定全天

   //儲存事件

   NSError *error = nil;

   [self.eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&error];

   NSLog(@"%@",error);

下面示例代碼用來删除月曆事件:

- (void)removeEvent {

           [self.eventStore removeEvent:eventArray.firstObject span:EKSpanThisEvent error:nil];