1 讀取系統日歷
let eventStore = EKEventStore() let tempFormatter = NSDateFormatter() tempFormatter.dateFormat = "dd.MM.yyyy HH:mm" //獲取一個時間段中的日歷事件 let startDate = tempFormatter.dateFromString("10.08.2016 15:10")! let endDate = tempFormatter.dateFromString("12.08.2016 15:30")! let predicate = eventStore.predicateForEventsWithStartDate(startDate, endDate: endDate, calendars: [eventStore.defaultCalendarForNewEvents]) //獲取這個時間段中的所有日程 let events = eventStore.eventsMatchingPredicate(predicate)
2 添加事件到系統日歷
let eventStore = EKEventStore()
eventStore.requestAccessToEntityType(.Event) { (granted, error) in dispatch_async(dispatch_get_main_queue(), { if error != nil { //發生錯誤 } else if !granted { //不允許訪問日歷 } else { //創建事件 let event = EKEvent(eventStore: eventStore) event.title = "lallallallal" let tempFormatter = NSDateFormatter() tempFormatter.dateFormat = "dd.MM.yyyy HH:mm" //創建一個時間段的日歷事件 event.startDate = tempFormatter.dateFromString("11.08.2016 15:20")! event.endDate = tempFormatter.dateFromString("11.08.2016 15:30")! //設置是否為全天事件 event.allDay = false //設置事件的提醒時間(相對時間)提前15分鍾提醒 event.addAlarm(EKAlarm(relativeOffset: -60.0 * 15.0)) //設置事件的提醒時間(絕對時間) //event.addAlarm(EKAlarm(absoluteDate: NSDate(timeInterval: -60 * 15, sinceDate: event.startDate))) event.calendar = eventStore.defaultCalendarForNewEvents //保存事件,添加到日歷中 do { try eventStore.saveEvent(event, span: .ThisEvent, commit: true) } catch { } } }) }
3 分析:
日歷分為兩類,一類用於存儲事件的日歷,一類用於存儲提醒的日歷。
EventKit庫框架授權訪問用戶的日歷app及提醒事項app。盡管是用兩個不同的應用來顯示用戶的日歷和提醒數據,但卻是同一個框架來維護這份數據。同樣地,存儲這份數據的數據庫叫做日歷數據庫,同時容納日歷和提醒信息。
事件庫不但允許你的應用獲取用戶已經存在的日歷及提醒數據,而且它可以讓你的應用為任何日歷創建新的事件和提醒。另外,事件庫讓用戶可以編輯和刪除他們的事件和提醒(整體叫做“日歷項”)。如果日歷數據庫有來自你的應用外部的更改發生,事件庫可以通過通知監測到,這樣你的應用可以做出適當的響應。使用事件庫對日歷項所做的更改會自動地同步到相關的日歷。
(1)讀寫日歷數據庫
你可以使用 EKEventStore
類從用戶的日歷數據庫中獲取、創建、編輯和刪除事件。你可以獲取匹配你提供的謂詞的事件自定義的一組事件,或通過唯一標識獲取一個單獨的事件。你獲取到一個事件后,可以使用 EKEvent
類的屬性獲取訪問該事件相關的日歷信息。同樣的,你可以通過設置 EKEvent
類的屬性來修改該事件的日歷信息。
- 連接到事件庫
在 iOS 5 及以后版本系統中,使用默認的初始化器:
let eventStore = EKEventStore()
在 iOS 6 及以后版本,你必須在事件庫初始化后,使用
requestAccessToEntityType:completion:
方法請求使用用戶的日歷數據庫。請求訪問某個實體類型會異步提示用戶允許或禁止你的應用使用他們的日歷信息。你應該處理用戶授權或禁止你的應用訪問權的各種狀況:eventStore.requestAccessToEntityType(.Event) { (granted, error) in
}EKEventStore
對象需要相對較大量的時間來初始化和釋放。因此,你不應該為每一個事件相關的任務都初始化和釋放事件庫。相反,在你的應用加載時,初始化一個事件庫,然后反復地使用這一個來確保連接一直可用。事件庫實例不應該在其它事件開發包相對的對象釋放前被釋放,否則可能發生意想不到的狀態。 - 獲取事件
有兩種方式獲取事件。通過謂詞或搜索查詢獲取,會返回零個或多個與給定查詢匹配的事件。通過唯一標識獲取會返回與給定標識相符的唯一的一個事件。
注意:從日歷數據庫獲取事件並不一定按時間順序返回。要通過日期排序EKEvent
對象的數組,可以在數組上調用sortedArrayUsingSelector:
方法,並提供compareStartDateWithEvent:
方法的選擇器。 - 使用謂詞
通常是要獲得屬於某一日期范圍的事件。EKEventStore 的
eventsMatchingPredicate:
方法獲取屬於你提供的謂詞中指定的日期范圍的所有事件。
注意:盡管eventsMatchingPredicate:
方法接受一個NSPredicate
類型的參數,但你必須提供一個用
EKEventStore
的方法predicateForEventsWithStartDate:endDate:calendars:
創建的謂詞。
你可以指定一個日歷的子集來搜索,這需要傳遞一個EKCalendar
對象的數組作為predicateForEventsWithStartDate:endDate:calendars:
方法的 calendars 參數。你可以從事件庫的calendarsForEntityType:
方法獲得用戶的不同類型的日歷。如果傳一個 nil 值,那么就是告訴這個方法獲取用戶的所有日歷。
因為方法eventsMatchingPredicate:
是同步的,而你可能並不想在你的應用主線程中運行它。如果要異步執行的話,那么使用dispatch_async
函數或使用一個NSOperation
對象,就可以在另一個線程中運行該方法了。 - 使用唯一標識
如果你之前使用謂詞獲得了一個事件並知道它的唯一標識,那么你可以使用EKEventStore
的eventWithIdentifier:
方法來再次獲取該事件。如果它是一個循環事件,那么這個方法就會返回第一次出現的該事件。你可以使用屬性eventIdentifier
獲得事件的唯一標識。 - 創建及編輯事件
使用 事件EKEvent
的eventWithEventStore: 方法創建一個新的事件。 - 保存和移除事件
提示:如果你的應用修改用戶的日歷數據庫,它必須在這之前先從用戶獲得確認。應用在未得到用戶的特定指示的情況下決不可能修改日歷數據庫。
你對事件的修改不是持久化的,直到你保存它們為止。使用
EKEventStore
的 saveEvent:span:commit:error: 方法保存你的修改到日歷數據庫中。如果你要從日歷數據庫移除事件,使用 EKEventStore 的 removeEvent:span:commit:error: 方法。無論你保存或移除事件,各自實現的方法都會自動所做的修改到該事件所屬於的日歷(CalDav、Exchange等等)。如果你保存一個循環事件,你可以通過給
saveEvent:span:commit:error:
方法的參數 span 指定EKSpanFutureEvents
來使你的更改應用到所有未來出現的該事件中。同樣地,你也可以指定removeEvent:span:commit:error:
方法的 span 參數值為EKSpanFutureEvents
來移除一個事件的所有未來的出現。注意:如果你給 commit 參數傳了 NO 值,那么要確保稍侯調用
commit:
方法以持久保存你的更改(譯者注:默認傳 YES 會立即持久保存更改)。