#import <EventKit/EventKit.h>
- (void)saveEvent:(id)sender {
????//事件市場
????EKEventStore *eventStore = [[EKEventStore alloc] init];
????//6.0及以上通過下面方式寫入事件
????if?([eventStore respondsToSelector:@selector(requestAccessToEntityType:completion:)]) ? ?{
????????// the selector is available, so we must be on iOS 6 or newer
????????[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL?granted,?NSError?*error) {
????????????dispatch_async(dispatch_get_main_queue(), ^{
????????????????if?(error) {
?????????????????//錯(cuò)誤細(xì)心
? ? ? ? ? ? ? ? // display error message here
?? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ? else?if?(!granted) {
????????????????????//被用戶拒絕烤宙,不允許訪問日歷
????????????????????// display access denied error message here
????????????????} else{
????????????????????// access granted
????????????????????// ***** do the important stuff here *****
????????????????????//事件保存到日歷
????????????????????//創(chuàng)建事件
????????????????????EKEvent *event? = [EKEvent eventWithEventStore:eventStore];
????????????????????event.title???? = @"哈哈哈佣渴,我是日歷事件啊";
????????????????????event.location = @"我在杭州西湖區(qū)留和路";
????????????????????NSDateFormatter?*tempFormatter = [[NSDateFormatter?alloc]init];
????????????????????[tempFormatter setDateFormat:@"dd.MM.yyyy HH:mm"];
????????????????????event.startDate = [[NSDate?alloc]init ];
????????????????????event.endDate?? = [[NSDate?alloc]init ];
????????????????????event.allDay =?YES;
????????????????????//添加提醒
????????????????????[event addAlarm:[EKAlarm alarmWithRelativeOffset:60.0f * -60.0f * 24]];
????????????????????[event addAlarm:[EKAlarm alarmWithRelativeOffset:60.0f * -15.0f]];
????????????????????[event setCalendar:[eventStore defaultCalendarForNewEvents]];
????????????????????NSError?*err;
????????????????????[eventStore saveEvent:event span:EKSpanThisEvent error:&err];
????????????????????UIAlertView *alert = [[UIAlertView alloc]
??????????????????????????????????????????initWithTitle:@"Event Created"
??????????????????????????????????????????message:@"Yay!?"
??????????????????????????????????????????delegate:nil
??????????????????????????????????????????cancelButtonTitle:@"Okay"
??????????????????????????????????????????otherButtonTitles:nil];
????????????????????[alert show];
????????????????????NSLog(@"保存成功");
????????????????}
????????????});
????????}];
????} else ?{
????????// this code runs in iOS 4 or iOS 5
????????// ***** do the important stuff here *****
????????//4.0和5.0通過下述方式添加
????????//保存日歷
????????EKEvent *event? = [EKEvent eventWithEventStore:eventStore];
????????event.title???? = @"哈哈哈揍愁,我是日歷事件啊";
????????event.location = @"我在杭州西湖區(qū)留和路";
????????NSDateFormatter?*tempFormatter = [[NSDateFormatter?alloc]init];
????????[tempFormatter setDateFormat:@"dd.MM.yyyy HH:mm"];
????????event.startDate = [[NSDate?alloc]init ];
????????event.endDate?? = [[NSDate?alloc]init ];
????????event.allDay =?YES;
????????[event addAlarm:[EKAlarm alarmWithRelativeOffset:60.0f * -60.0f * 24]];
????????[event addAlarm:[EKAlarm alarmWithRelativeOffset:60.0f * -15.0f]];
????????[event setCalendar:[eventStore defaultCalendarForNewEvents]];
????????NSError?*err;
????????[eventStore saveEvent:event span:EKSpanThisEvent error:&err];
????????UIAlertView *alert = [[UIAlertView alloc]
??????????????????????????????initWithTitle:@"Event Created"
??????????????????????????????message:@"Yay!?"
??????????????????????????????delegate:nil
??????????????????????????????cancelButtonTitle:@"Okay"
??????????????????????????????otherButtonTitles:nil];
????????[alert show];
?? ? ? ?NSLog(@"保存成功");
????}
}
分析:事件提醒開發(fā)包(EventKit)由事件庫、事件源兽狭、日歷和事件/提醒組成七芭,他們的關(guān)系是:事件庫用于直接操作日歷數(shù)據(jù)庫,日歷數(shù)據(jù)庫中的數(shù)據(jù)按事件源褐捻、日歷和事件/提醒三級(jí)進(jìn)行分類組織爬范。每個(gè)事件源對(duì)應(yīng)一個(gè)準(zhǔn)帳戶,該帳戶下可以有多個(gè)日歷弱匪,日歷分兩類青瀑,一類是用于存儲(chǔ)事件的日歷,一類是用于存儲(chǔ)提醒的日歷萧诫。這里所說的存儲(chǔ)斥难,實(shí)際就是分類,反過來的帘饶,根據(jù)子項(xiàng)對(duì)父項(xiàng)進(jìn)行分類哑诊。就如兩口缸,一口裝水及刻,一口沙子一樣镀裤,這個(gè)缸就是上面提及的日歷,水相當(dāng)于事件缴饭,沙子相當(dāng)于提醒暑劝。一戶人家的院子里可以擺好多口缸,這個(gè)院子就相當(dāng)于帳戶颗搂,有兩個(gè)默認(rèn)帳戶担猛,一個(gè)是Local,一個(gè)是Other丢氢。帳戶的類型傅联,還可能有iCloud或Gmail帳號(hào)等,一般是郵箱附帶的疚察,所以就默認(rèn)對(duì)應(yīng)著該郵箱地址了蒸走。就像 大戶人家的總管,管好每戶的院子稍浆,還有每個(gè)院子里的缸一樣载碌,事件庫直接管理所有的帳戶和日歷猜嘱,還有日歷下的事件或提醒。管理包括增加嫁艇、修改朗伶、查詢、刪除(CURD)步咪。
日歷和提醒入門(Introduction to Calendars and Reminders)
事件庫框架授權(quán)訪問用戶的Calendar.app和Reminders.app 應(yīng)用的信息论皆。盡管是用兩個(gè)不同的應(yīng)用顯示用戶的日歷和提醒數(shù)據(jù),但確是同一個(gè)框架維護(hù)這份數(shù)據(jù)猾漫。同樣地点晴,存儲(chǔ)這份數(shù)據(jù)的數(shù)據(jù)庫叫做日歷數(shù)據(jù)庫,同時(shí)容納日歷和提醒信息悯周。
The Event Kit framework grants access to users’Calendar.appandReminders.appinformation. Although two different apps display users’ calendar and reminder data, the same framework manipulates the data. Similarly, the database that stores this data, called the Calendar database, holds both calendar and reminder information.
圖示 1-1 事件庫結(jié)構(gòu)?Figure I-1?Event Kit architecture
事件庫不但允許你的應(yīng)用獲取用戶已經(jīng)存在的日歷及提醒數(shù)據(jù)粒督,而且它可以讓你的應(yīng)用為任何日歷創(chuàng)建新的事件和提醒。另外禽翼,事件庫讓用戶可以編輯和刪除他們的事件和提醒(整體叫做“日歷項(xiàng)”)屠橄。更高級(jí)的任務(wù),諸如添加鬧鐘或指定循環(huán)事件闰挡,也可以使用事件庫完成锐墙。如果日歷數(shù)據(jù)庫有來自你的應(yīng)用外部的更改發(fā)生,事件庫可以通過通知監(jiān)測(cè)到长酗,這樣你的應(yīng)用可以做出適當(dāng)?shù)捻憫?yīng)溪北。使用事件庫對(duì)日歷項(xiàng)所做的更改會(huì)自動(dòng)地同步到相關(guān)的日歷(CalDAV -?是一種效率手冊(cè)同步協(xié)議,有些效率手冊(cè) 如 Apple iCal夺脾、Mozilla Lightning/Sunbird 使用這一協(xié)議使其信息能與其它效率手冊(cè) 如 Yahoo! 效率手冊(cè) 進(jìn)行交換之拨;Exchange 等)。
本文檔描述事件庫的概念及通用的編程任務(wù)劳翰。如果你想要從你的應(yīng)用來顯示或編輯日歷事件和/或提醒數(shù)據(jù)敦锌,那么你應(yīng)該閱讀本文檔。事件庫提供了有限的對(duì)用戶日歷數(shù)據(jù)庫的訪問佳簸;但它并未包含期望實(shí)現(xiàn)完整特性的日歷或提醒應(yīng)用所需的每一個(gè)功能乙墙,諸如出席者和帳戶。
Event Kit not only allows your app to retrieve users’ existing calendar and reminder data, but it also lets your app create new events and reminders for any of their calendars. In addition, Event Kit lets users edit and delete their events and reminders (collectively known as “calendar items”). More advanced tasks, such as adding alarms or specifying recurring events, can be achieved with Event Kit as well. If a change to the Calendar database occurs from outside of your app, Event Kit is able to detect the change by notification so your app can act appropriately. Changes made to calendar items with Event Kit are automatically synced to the associated calendar (CalDAV, Exchange, and so on).
This document describes Event Kit concepts and common programming tasks. You should read this document if you want to display or edit calendar events and/or reminder data from within your app. Event Kit provides limited access to a user’s Calendar database; it does not include everything that would be desired for implementing a full-featured calendar or reminder app, such as adding attendees or accounts.
概覽(At a Glance)
本文檔包含如下幾章生均,這些內(nèi)容描述了如何在你的應(yīng)用內(nèi)集成用戶的日歷和提醒數(shù)據(jù):
“讀寫日歷事件” 描述了如何獲取听想、創(chuàng)建和修改日歷事件。
“讀寫提醒” 描述了如何獲取马胧、創(chuàng)建和修改提醒汉买。
“配置鬧鐘” 描述了如何附加鬧鐘到一個(gè)日歷項(xiàng)。
“創(chuàng)建循環(huán)的事件” 描述了如何使一個(gè)事件變成循環(huán)事件佩脊。
“監(jiān)視日歷數(shù)據(jù)庫的外部更改” 描述了如何注冊(cè)通知以關(guān)注日歷數(shù)據(jù)庫的外部更改蛙粘。
“提供事件界面” 描述了如何顯示事件視圖控制器以允許你的用戶來創(chuàng)建和編輯事件垫卤。
This document contains the following chapters, which describe how to integrate with users’ calendar and reminder data within your app:
“Reading and Writing Calendar Events” explains how to retrieve, create, and modify calendar events.
“Reading and Writing Reminders” explains how to retrieve, create, and modify reminders.
“Configuring Alarms” explains how to attach alarms to a calendar item.
“Creating Recurring Events” explains how to make an event a recurring event.
“Observing External Changes to the Calendar Database” explains how to register for notifications regarding external changes to the Calendar database.
“Providing Interfaces for Events” explains how to display event view controllers to allow your users to create and edit events.
參見(See Also)
本文檔是下面的示例代碼和參考手冊(cè)的配套指南:
SimpleEKDemo是一個(gè)使用事件庫中事件的示例代碼工程。
Event Kit Framework Reference提供了一個(gè)事件庫 API 的較深入的描述出牧,這些 API 就是一個(gè)訪問用戶的日歷數(shù)據(jù)庫的框架穴肘。
Event Kit UI Framework Reference詳細(xì)說明了事件庫用戶界面的 API,就是一個(gè) iOS專有的框架舔痕,它提供了一些視圖控制器用于顯示和編輯日歷事件评抚。
This document is a companion guide to the following sample code and references:
SimpleEKDemo is an example sample code project that utilizes events in Event Kit.
Event Kit Framework Reference provides an in-depth description of the Event Kit API, a framework that grants access to a user’s Calendar database.
Event Kit UI Framework Reference details the Event Kit UI API, an iOS-specific framework that provides view controllers for displaying and editing calendar events. ??
讀寫日歷事件(Reading and Writing Calendar Events )
你可以使用EKEventStore類從用戶的日歷數(shù)據(jù)庫中獲取、創(chuàng)建伯复、編輯和刪除事件慨代。你可以獲取匹配你提供的謂詞的事件自定義的一組事件,或通過唯一標(biāo)識(shí)獲取一個(gè)單獨(dú)的事件啸如。你獲取到一個(gè)事件后侍匙,可以使用EKEvent類的屬性獲取訪問該事件相關(guān)的日歷信息。同樣的叮雳,你可以通過設(shè)置EKEvent類的屬性來修改該事件的日歷信息丈积。
You can fetch, create, edit, and delete events from a user’s Calendar database using theEKEventStoreclass. You can fetch a custom set of events that match a predicate you provide, or you can fetch an individual event by its unique identifier. After you fetch an event, you can access its associated calendar information with the properties of theEKEventclass. Likewise, you can modify its calendar?information by setting the properties of theEKEventclass.
連接到事件庫(Connecting to the Event Store)
在 iOS 5 及以后版本系統(tǒng)中,使用默認(rèn)的初始化器:
On iOS 5 and later, initialize anEKEventStoreobject with the default initializer:
EKEventStore *store = [[EKEventStore alloc] init];
在 iOS 6 及以后版本债鸡,你必須在事件庫初始化后,使用requestAccessToEntityType:completion:方法請(qǐng)求使用用戶的日歷數(shù)據(jù)庫铛纬。請(qǐng)求訪問某個(gè)實(shí)體類型會(huì)異步提示用戶允許或禁止你的應(yīng)用使用他們的日歷信息厌均。你應(yīng)該處理用戶授權(quán)或禁止你的應(yīng)用訪問權(quán)的各種狀況:
On iOS 6 and later, you must request access to use the user’s Calendar database with therequestAccessToEntityType:completion:method after the event store is initialized. Requesting access to an entity type asynchronously prompts the user to allow or deny your app from using their calendar information. You should handle cases for when the user grants and denies access to your app:
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
? ? // handle access here
}];
On OS X and later, initialize anEKEventStoreobject with the designated initializerinitWithAccessToEntityTypes::
EKEventStore *store = [[EKEventStore alloc] initWithAccessToEntityTypes:EKEntityMaskEvent];
You do not need to request access to use the user’s Calendar database on OS X, because access is automatically granted.
EKEventStore對(duì)象需要相對(duì)較大量的時(shí)間來初始化和釋放。因此告唆,你不應(yīng)該為每一個(gè)事件相關(guān)的任務(wù)都初始化和釋放事件庫棺弊。相反,在你的應(yīng)用加載時(shí)擒悬,初始化一個(gè)事件庫模她,然后反復(fù)地使用這一個(gè)來確保連接一直可用。
事件庫實(shí)例不應(yīng)該在其它事件開發(fā)包相對(duì)的對(duì)象釋放前被釋放懂牧,否則可能發(fā)生意想不到的狀態(tài)侈净。
AnEKEventStoreobject requires a relatively large amount of time to initialize and release. Consequently, you should not initialize and release a separate event store for each event-related task. Instead, initialize a single event store when your app loads, and use it repeatedly to ensure that your connection is long-lived.
An event store instance must not be released before other Event Kit objects; otherwise, undefined behavior may occur.
獲取事件(Retrieving Events)
有兩種方式獲取事件。通過謂詞或搜索查詢獲取僧凤,會(huì)返回零個(gè)或多個(gè)與給定查詢匹配的事件畜侦。通過唯一標(biāo)識(shí)獲取會(huì)返回與給定標(biāo)識(shí)相符的唯一的一個(gè)事件。
There are two ways to retrieve events. Fetching via predicates, or search query, will return zero or more events that match a given query. Fetching via unique identifiers will return a single event that corresponds to the given identifier.
注意:從日歷數(shù)據(jù)庫獲取事件并不一定按時(shí)間順序返回躯保。要通過日期排序EKEvent對(duì)象的數(shù)組旋膳,可以在數(shù)組上調(diào)用sortedArrayUsingSelector:方法,并提供compareStartDateWithEvent:方法的選擇器途事。
Note:Retrieving events from the Calendar database does not necessarily return events in chronological order. To sort an array ofEKEventobjects by date, callsortedArrayUsingSelector:on the array, providing the selector for thecompareStartDateWithEvent:method.
使用謂詞(Using Predicates )?
通常是要獲得屬于某一日期范圍的事件验懊。EKEventStore 的eventsMatchingPredicate:方法獲取屬于你提供的謂詞中指定的日期范圍的所有事件擅羞。
It’s common to fetch events that fall within a date range. TheEKEventStore?methodeventsMatchingPredicate:fetches all events that fall within the date range specified in the predicate you provide.
列表 1-1 展示了如何獲取發(fā)生在一天前和當(dāng)前之后一年之內(nèi)的所有事件。
Listing 1-1?demonstrates how to fetch all events that occur between one day before and one year after the current date.
注意:盡管eventsMatchingPredicate:方法接受一個(gè)NSPredicate類型的參數(shù)义图,但你必須提供一個(gè)用EKEventStore的方法predicateForEventsWithStartDate:endDate:calendars:創(chuàng)建的謂詞减俏。
Note:Although theeventsMatchingPredicate:method accepts a parameter of typeNSPredicate, you must supply a predicate created with theEKEventStoremethodpredicateForEventsWithStartDate:endDate:calendars:.
列表 1-1 使用謂詞獲取事件?Listing 1-1?Fetching events with a predicate
// 獲取適當(dāng)?shù)娜掌冢℅et the appropriate calendar)
NSCalendar *calendar = [NSCalendar currentCalendar];
// 創(chuàng)建起始日期組件(Create the start date components)
NSDateComponents *oneDayAgoComponents = [[NSDateComponents alloc] init];
oneDayAgoComponents.day = -1;
NSDate *oneDayAgo = [calendar dateByAddingComponents:oneDayAgoComponents
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? toDate:[NSDate date]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? options:0];
// 創(chuàng)建結(jié)束日期組件(Create the end date components)
NSDateComponents *oneYearFromNowComponents = [[NSDateComponents alloc] init];
oneYearFromNowComponents.year = 1;
NSDate *oneYearFromNow = [calendar dateByAddingComponents:oneYearFromNowComponents
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? toDate:[NSDate date]
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? options:0];
// 用事件庫的實(shí)例方法創(chuàng)建謂詞 (Create the predicate from the event store's instance method)
NSPredicate *predicate = [store predicateForEventsWithStartDate:oneDayAgo
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? endDate:oneYearFromNow
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? calendars:nil];
// 獲取所有匹配該謂詞的事件(Fetch all events that match the predicate)
NSArray *events = [store eventsMatchingPredicate:predicate];
你可以指定一個(gè)日歷的子集來搜索,這需要傳遞一個(gè)EKCalendar對(duì)象的數(shù)組作為predicateForEventsWithStartDate:endDate:calendars:方法的calendars參數(shù)歌溉。你可以從事件庫的calendarsForEntityType:方法獲得用戶的不同類型的日歷垄懂。如果傳一個(gè) nil 值,那么就是告訴這個(gè)方法獲取用戶的所有日歷痛垛。
You can specify a subset of calendars to search by passing an array ofEKCalendarobjects as thecalendarsparameter of thepredicateForEventsWithStartDate:endDate:calendars:method. You can get the user’s calendars from the event store’scalendarsForEntityType:method. Passingnil?tells the method to fetch from all of the user’s calendars.
因?yàn)榉椒?a target="_blank" rel="nofollow">eventsMatchingPredicate:是同步的草慧,而你可能并不想在你的應(yīng)用主線程中運(yùn)行它。如果要異步執(zhí)行的話匙头,那么使用dispatch_async函數(shù)或使用一個(gè)NSOperation對(duì)象漫谷,就可以在另一個(gè)線程中運(yùn)行該方法了。
Because theeventsMatchingPredicate:method is synchronous, you may not want to run it on your app’s main thread. For asynchronous behavior, run the method on another thread with thedispatch_asyncfunction or with anNSOperationobject.
使用唯一標(biāo)識(shí)(Using Unique Identifiers )
如果你之前使用謂詞獲得了一個(gè)事件并知道它的唯一標(biāo)識(shí)蹂析,那么你可以使用EKEventStore的eventWithIdentifier:方法來再次獲取該事件舔示。如果它是一個(gè)循環(huán)事件,那么這個(gè)方法就會(huì)返回第一次出現(xiàn)的該事件电抚。你可以使用屬性eventIdentifier獲得事件的唯一標(biāo)識(shí)惕稻。
If you know the event’s unique identifier because you fetched it previously with a predicate, you can use theEKEventStoremethodeventWithIdentifier:to fetch the event. If it is a recurring event, this method will return the first occurrence of the event. You can get an event’s unique identifier with theeventIdentifierproperty.
創(chuàng)建及編輯事件(Creating and Editing Events)
注意:如果你正在 iOS上開發(fā),那么你可以選擇使用事件庫用戶界面框架提供的事件視圖控制器來讓用戶修改事件數(shù)據(jù)蝙叛。有關(guān)如何使用這些事件視圖控制器的信息俺祠,參見“為事件提供界面〗枇保”
使用 事件EKEvent的eventWithEventStore:方法創(chuàng)建一個(gè)新的事件蜘渣。
你可以通過設(shè)置一個(gè)新的事件或先前從日歷數(shù)據(jù)庫獲取的事件的對(duì)應(yīng)屬性來編輯事件。你可以編輯的詳細(xì)內(nèi)容包括:
事件的標(biāo)題用title屬性
與事件關(guān)聯(lián)的日歷用屬性calendar
與事件相關(guān)的鬧鐘用alarms屬性 (參見“配置鬧鐘”以獲得更多詳細(xì)信息)
如果一個(gè)事件是循環(huán)事件肺然,那么它的循環(huán)規(guī)則用屬性recurrenceRules(參見“創(chuàng)建循環(huán)事件”以獲得更多詳細(xì)信息)
Note:?If you’re developing on iOS, you have the option of letting users modify event data with the event view controllers provided in the Event Kit UI framework. For information on how to use these event view controllers, see“Providing Interfaces for Events.”
Create a new event with theeventWithEventStore:method of theEKEventclass.
You can edit the details of a new event or an event you previously fetched from the Calendar database by setting the event’s corresponding properties. Some of the details you can edit include:
The event’s title with thetitleproperty
The event’s start and end dates with thestartDateandendDateproperties
The calendar with which the event is associated with thecalendarproperty
The alarms associated with the event with thealarmsproperty (see“Configuring Alarms”?for more details)
The event’s recurrence rule, if it is a repeating event, with therecurrenceRulesproperty (see“Creating Recurring Events”?for more details)
保存和移除事件(Saving and Removing Events)
提示:如果你的應(yīng)用修改用戶的日歷數(shù)據(jù)庫蔫缸,它必須在這之前先從用戶獲得確認(rèn)。應(yīng)用在未得到用戶的特定指示的情況下決不可能修改日歷數(shù)據(jù)庫际起。
你對(duì)事件的修改不是持久化的拾碌,直到你保存它們?yōu)橹埂J褂肊KEventStore的saveEvent:span:commit:error:方法保存你的修改到日歷數(shù)據(jù)庫中加叁。如果你要從日歷數(shù)據(jù)庫移除事件倦沧,使用?EKEventStore 的removeEvent:span:commit:error:方法。無論你保存或移除事件它匕,各自實(shí)現(xiàn)的方法都會(huì)自動(dòng)所做的修改到該事件所屬于的日歷(CalDav展融、Exchange等等)。
如果你保存一個(gè)循環(huán)事件豫柬,你可以通過給saveEvent:span:commit:error:方法的參數(shù) span 指定EKSpanFutureEvents來使你的更改應(yīng)用到所有未來出現(xiàn)的該事件中告希。同樣地扑浸,你也可以指定removeEvent:span:commit:error:方法的 span 參數(shù)值為EKSpanFutureEvents來移除一個(gè)事件的所有未來的出現(xiàn)。
注意:如果你給 commit 參數(shù)傳了 NO 值燕偶,那么要確保稍侯調(diào)用commit:方法以持久保存你的更改(譯者注:默認(rèn)傳 YES 會(huì)立即持久保存更改)喝噪。
Important:?If your app modifies a user’s Calendar database,?it must get confirmation from the user before doing so. An app should never modify the Calendar database without specific instruction from the user.
Changes you make to an event are not permanent until you save them. Save your changes to the Calendar database with theEKEventStoremethodsaveEvent:span:commit:error:. If you want to remove an event from the Calendar database, use theEKEventStoremethodremoveEvent:span:commit:error:. Whether you are saving or removing an event, implementing the respective method automatically syncs your changes with the calendar the event belongs to (CalDAV, Exchange, and so on).
If you are saving a recurring event, your changes can apply to all future occurrences of the event by specifyingEKSpanFutureEventsfor thespanparameter of thesaveEvent:span:commit:error:method. Likewise, you can remove all future occurrences of an event by specifyingEKSpanFutureEventsfor thespanparameter of theremoveEvent:span:commit:error:method.
Note:?If you passNOto the?commit?parameter, make sure that you later invoke thecommit:method to permanently save your changes.
執(zhí)行批量事件操作(Performing Batch Operations on Events)
你可以在EKEventStore的enumerateEventsMatchingPredicate:usingBlock:方法執(zhí)行給定的謂詞匹配的所有事件上執(zhí)行同一個(gè)操作。你必須為上述方法使用EKEventStore的predicateForEventsWithStartDate:endDate:calendars:方法創(chuàng)建謂詞指么。你提供的操作是?EKEventSearchCallback?類型的塊酝惧。
You can perform an operation on all events that match a provided predicate with theEKEventStoremethodenumerateEventsMatchingPredicate:usingBlock:. You must create the predicate for this method with theEKEventStoremethodpredicateForEventsWithStartDate:endDate:calendars:. The operation you provide is a block of typeEKEventSearchCallback.
typedef void (^EKEventSearchCallback)(EKEvent *event, BOOL *stop);
塊接收兩個(gè)參數(shù)(The block is passed two parameters):
event
當(dāng)前被操作的事件(The event that is currently being operated on).
stop
一個(gè)布爾值,它決定當(dāng)前塊返回后enumerateEventsMatchingPredicate:usingBlock:方法是否應(yīng)該停止繼續(xù)處理事件伯诬。如果是 YES晚唇,那么與該謂詞匹配的任何未處理的事件仍保持未處理狀態(tài)。
提示:記住盗似,使用該方法會(huì)引起對(duì)用戶的日歷數(shù)據(jù)庫的有效的修改哩陕。確認(rèn)在你向用戶請(qǐng)求批準(zhǔn)時(shí),讓用戶清楚地知道你所要執(zhí)行的操作赫舒。
A Boolean value determining whetherenumerateEventsMatchingPredicate:usingBlock:should stop processing events when this block returns. IfYES, any event that matches the predicate but has not yet been processed will remain unprocessed.
Important:?Keep in mind that using this method can result in significant changes to the user’s Calendar database. Make sure the user is fully informed of the actions you are about to perform when you request user confirmation.
Because theenumerateEventsMatchingPredicate:usingBlock:method is synchronous, you may not want to run it on your app’s main thread. For asynchronous behavior, run the method on another thread with thedispatch_asyncfunction or with anNSOperationobject.
讀寫提醒(Reading and Writing Reminders)
提醒就是一些可以關(guān)聯(lián)到特定時(shí)間或位置的任務(wù)悍及。他們與日歷事件很相似,但可以被標(biāo)識(shí)為完成并且可以不必跨躍一段確切的時(shí)間接癌。
因?yàn)?a target="_blank" rel="nofollow">EKReminder繼承自EKCalendarItem心赶,所以你可以在提醒上執(zhí)行與在事件上一樣的方法,諸如使用addAlarm:方法添加一個(gè)鬧鐘缺猛,或使用addRecurrenceRule:方法設(shè)置一個(gè)循環(huán)規(guī)則园担。
Reminders are tasks that may be tied to a specific time or location. They are similar to calendar events, but can be marked complete and may not necessarily span an exact period of time.
BecauseEKReminderinherits fromEKCalendarItem, you can perform the same methods on a reminder as you would on an event, such as adding an alarm withaddAlarm:or setting a recurrence rule withaddRecurrenceRule:.
獲取提醒(Retrieving Reminders)
和事件一樣,你必須先建立與事件庫的連接枯夜,才能訪問已存在的提醒。如果你之前沒做過事件庫的連接操作艰山,那么參見“連接到事件庫”湖雹。
要在 OS X 上初始訪問提醒的連接,傳遞的參數(shù)不是EKEntityMaskEvent?而是EKEntityMaskReminder曙搬。
As with events, you must first establish a connection to the event store to access existing reminders. See“Connecting to the Event Store”?if you have not already done so.
To initialize a connection with access to reminders on OS X, passEKEntityMaskReminderinstead ofEKEntityMaskEvent.
EKEventStore *store = [[EKEventStore alloc] initWithAccessToEntityTypes:EKEntityMaskReminder];
在 iOS 6 及以后的版本中摔吏,事件庫初始化后,你必須使用requestAccessToEntityType:completion:請(qǐng)求對(duì)用戶日歷數(shù)據(jù)庫的訪問權(quán)纵装。請(qǐng)求某一實(shí)體類型的訪問權(quán)會(huì)提示用戶允許或禁止你的應(yīng)用使用日歷信息征讲。你應(yīng)該處理用戶授權(quán)或禁止訪問每種情況:
On iOS 6 and later, you must request access to use the user’s Calendar database with therequestAccessToEntityType:completion:method after the event store is initialized. Requesting access to an entity type asynchronously prompts the user to allow or deny your app from using their calendar information. You should handle cases for when the user grants and denies access to your app:
[store requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError *error) {
? ? // handle access here
}];
在 OS X 上你不需要請(qǐng)求用戶提醒的訪問權(quán),因?yàn)樵L問權(quán)是默認(rèn)授予的(譯者注:iOS 模擬器上也是默認(rèn)授予的)橡娄。
正如搜索事件一樣诗箍,也有兩種途徑來獲取提醒。
You do not need to request access for the user’s reminders on OS X, because access is automatically granted.
Just like searching for events, there are two ways to retrieve reminders.
使用謂詞(Using Predicates)
你可以調(diào)用fetchRemindersMatchingPredicate:completion:方法來訪問與某一謂詞匹配的多個(gè)提醒挽唉。傳遞的謂詞可通過如下方法得到:
predicateForIncompleteRemindersWithDueDateStarting:ending:calendars:
找到(指定的日歷中)在某一選定的時(shí)間段內(nèi)所有未完成的提醒
predicateForCompletedRemindersWithCompletionDateStarting:ending:calendars:
找到(指定的日歷中)某一選定的時(shí)間段內(nèi)所有完成的提醒
predicateForRemindersInCalendars:
找到(指定的日歷中)所有提醒
你可以給 completion 參數(shù)傳一個(gè)塊來迭代所有匹配的提醒滤祖,如列表 2-1 所示:
You can callfetchRemindersMatchingPredicate:completion:to access multiple reminders that match a predicate. Pass a predicate returned by one of the following methods:
predicateForIncompleteRemindersWithDueDateStarting:ending:calendars:
finds incomplete reminders within an optional time period
predicateForCompletedRemindersWithCompletionDateStarting:ending:calendars:
finds completed reminders within an optional time period
predicateForRemindersInCalendars:
finds all reminders
You can iterate across matched reminders by passing a block to thecompletionargument, as shown inListing 2-1.
列表 2-1 使用謂詞獲取提醒
Listing 2-1?Fetching reminders with a predicate
NSPredicate *predicate = [store predicateForRemindersInCalendars:nil];
[store fetchRemindersMatchingPredicate:predicate completion:^(NSArray *reminders) {
? ? for (EKReminder *reminder in reminders) {
? ? ? ? // do something for each reminder
? ? }
}];
注意:不像通過謂詞獲取事件那樣(參見“使用謂詞”)筷狼,你可以通過謂詞異步獲取提醒,而無需分派到其它線程匠童。
如果你想要中止通過謂詞獲取的請(qǐng)求埂材,可以調(diào)用cancelFetchRequest:方法并傳遞之前由fetchRemindersMatchingPredicate:completion:方法返回的標(biāo)識(shí)。
Note:?Unlike fetching events via predicate (see“Using Predicates”), you can fetch reminders via predicate asynchronously without dispatching to another thread.
If you’d like to abort your fetch request by predicate, callcancelFetchRequest:while passing the identifier as returned byfetchRemindersMatchingPredicate:completion:.
使用唯一標(biāo)識(shí)(Using Unique Identifiers)
如果你知道一個(gè)從先前用謂詞獲取到的提醒的唯一標(biāo)識(shí)汤求,那么你可以調(diào)用calendarItemWithIdentifier:實(shí)例方法俏险,該方法可以獲取到任何與該標(biāo)識(shí)符匹配的日歷項(xiàng)(提醒或事件),而eventWithIdentifier:方法只能獲到事件扬绪。
If you know a specific reminder’s unique identifier from previously fetching it with a predicate, you can call thecalendarItemWithIdentifier:instance method.calendarItemWithIdentifier:can fetch any calendar item (reminders and events), whereaseventWithIdentifier:fetches only events.
創(chuàng)建及編輯提醒(Creating and Editing Reminders )
You can create reminders using thereminderWithEventStore:class method. Thetitleandcalendarproperties are required. The calendar for a reminder is the list with which it is grouped.
Like events, reminders can trigger time-based or location-based alarms to alert the user of a certain task. Read“Configuring Alarms”for more information on how to attach alarms to calendar items.
To associate a start date or due date with a reminder, use thestartDateComponentsanddueDateComponentsproperties. To complete a reminder, set thecompletedproperty toYES, which automatically setscompletionDateto the current date.
保存和移除提醒(Saving and Removing Reminders)
Important:?If your app modifies a user’s Calendar database,?it must get confirmation from the user before doing so. An app should never modify the Calendar database without specific instruction from the user.
Reminders are saved in a similar fashion to events. To save a reminder to the Calendar database, call thesaveReminder:commit:error:method. To remove an event, call theremoveReminder:commit:error:method.
Remember, thetitleandcalendarproperties must explicitly be set before you save your reminder.
Note:?Just like when saving or removing events, make sure that if you passNOto the?commit?parameter, you later invoke thecommit:method to save your changes.
配置鬧鐘(Configuring Alarms)
An easy way to alert users of their upcoming events is to give them the option of setting alarms for their calendar items. Regardless of the app that’s currently running, alarms come to the foreground as a notification and remind users of the scheduled event. If an alarm is set to a calendar event, the notification comes from the Calendar app; if an alarm is set to a reminder, the notification comes from the Reminders app. Alarms can be time-based, firing at a specified time, or location-based, firing when crossing a geofence (for more information about geofences, see“Setting Geofences”).
Alarms can be applied to both calendar events and reminders.
Note:?An alarm is not intended to serve as aUILocalNotification. An alarm requires you to create an event or reminder that is visible in the user’s Calendar or Reminders app. AUILocalNotificationis better suited for general purposes that don’t involve the Calendar database.
附加和移除鬧鐘(Attaching and Removing Alarms)?
You can add an alarm to an event with theaddAlarm:method. Alarms can be created with an absolute date or with an offset relative to the start date of the event. Alarms created with a relative offset must occur before or at the start date of the event.
In OS X, you can trigger an action alongside the alarm; for example, set:
TheemailAddressproperty to send an email
ThesoundNameproperty to play a sound
Theurlproperty to open a URL
You can remove an alarm from an event with theremoveAlarm:method.
設(shè)置地理圍欄(Setting Geofences)
Note:?Geofences are supported on both OS X and iOS, but they are more effective on mobile devices.
A geofence is a virtual border surrounding a geographic location that, when crossed, can trigger an alarm for an event. Geofences are a useful way to remind users of tasks they need to do when entering or exiting a certain region. For example, when a user leaves his workplace, an alarm can fire that reminds him to stop by the grocery store. As a developer, you have control over specifying the latitude and longitude of the center, as well as the radius of the geofence.
Configure a geofence for an event by creating an alarm and setting its structured location and proximity. Call thelocationWithTitle:method to create a structured location. To set longitude and latitude coordinates, pass aCLLocationto thegeoLocationproperty of the structured location returned. A value of0for theradiusproperty will use the system’s default radius; to choose a radius of your own, specify a value in meters.
While geofence-enabled alarms can be applied to events, they are more practical for reminders.
創(chuàng)建循環(huán)事件(Creating Recurring Events)
Recurring events repeat over a specified interval of time. To make an event a recurring event, assign it a recurrence rule, which describes when the event occurs. Recurrence rules are represented by instances of theEKRecurrenceRuleclass.
Recurrence is applicable to both calendar events and reminders. Unlike with recurring events, only the first incomplete reminder of a recurring set is obtainable. This is true with Event Kit as well as the Reminders app. When the reminder is completed, the next reminder in the recurrence set becomes available.
使用基本規(guī)則(Using Basic Rules)
You can create a recurrence rule with a simple daily, weekly, monthly, or yearly pattern using theinitRecurrenceWithFrequency:interval:end:method. You provide three values to this method:
The recurrence frequency
. This is a value of typeEKRecurrenceFrequencythat indicates whether the recurrence rule is daily, weekly, monthly, or yearly.
The recurrence interval
. This is an integer greater than 0 that specifies how often a pattern repeats. For example, if the recurrence rule is a weekly recurrence rule and its interval is1, then the pattern repeats every week. If the recurrence rule is a monthly recurrence rule and its interval is3, then the pattern repeats every three months.
The recurrence end
. This optional parameter is an instance of theEKRecurrenceEndclass, which indicates when the recurrence rule ends. The recurrence end can be based on a specific end date or on an amount of occurrences.
If you don’t want to specify an end for the recurrence rule, passnil.
使用復(fù)雜的規(guī)則(Using Complex Rules)
You can create a recurrence rule with a complex pattern using the?
method. As you do for a basic recurrence rule, you provide a frequency, an interval, and an optional end for the recurring event. In addition, you can provide a combination of optional values describing a custom rule, as listed inTable 4-1.
Table 4-1??Complex recurrence rule breakdown
Parameter nameAccepted valuesCan be combined withExample
days
The days of the week on which the event occurs.
An array ofEKRecurrenceDayOfWeekobjects.All recurrence rules except for daily recurrence rules.An array containingEKTuesdayandEKFridayobjects will create a recurrence that occurs every Tuesday and Friday.
monthDays
The days of the month on which the event occurs.
An array of nonzeroNSNumberobjects ranging from –31 to 31. Negative values indicate counting backward from the end of the month.Monthly recurrence rules only.An array containing the values1and–1will create a recurrence that occurs on the first and last day of every month.
months
The months of the year in which the event occurs.
An array ofNSNumberobjects with values ranging from 1 to 12, corresponding to Gregorian calendar months.Yearly recurrence rules only.If your originating event occurs on January 10, you can provide an array containing the values1and2to create a recurrence that occurs every January 10 and February 10.
weeksOfTheYear
The weeks of the year in which the event occurs.
An array of nonzeroNSNumberobjects ranging from –53 to 53. Negative values indicate counting backward from the end of the year.Yearly recurrence rules only.If your originating event occurs on a Wednesday, you can provide an array containing the values1and–1to create a recurrence that occurs on the Wednesday of the first and last weeks of every year. If a specified week does not contain a Wednesday in the current year, as can be the case for the first or last week of a year, the event does not occur.
daysOfTheYear
The days of the year on which the event occurs.
An array of nonzeroNSNumberobjects ranging from –366 to 366. Negative values indicate counting backward from the end of the year.Yearly recurrence rules only.You can provide an array containing the values1and–1to create a recurrence that occurs on the first and last day of every year.
setPositions
The occurrences to include in the recurrence rule. This filter is applied to the set of occurrences determined from the other parameters you provide.
An array of nonzeroNSNumberobjects ranging from –366 to 366. Negative values indicate counting backward from the end of the list of occurrences.All recurrence rules except for daily recurrence rules.If you provide an array containing the values1and–1to a yearly recurrence rule that has specified Monday through Friday as its value for days of the week, the recurrence occurs only on the first and last weekday of every year.
You can provide values for any number of the parameters inTable 4-1. Parameters that don’t apply to a particular recurrence rule are ignored. If you provide a value for more than one of the above parameters, the recurrence occurs only on days that apply to all provided values.
Once you have created a recurrence rule, you can apply it to a calendar event or reminder with theaddRecurrenceRule:instance method ofEKCalendarItem.
監(jiān)視日歷數(shù)據(jù)庫的外部更改(Observing External Changes to the Calendar Database)
It’s possible for another process or app to modify the Calendar database while your app is running. If your app fetches calendar events or reminders, you should register to be notified about changes to the Calendar database. By doing so, you ensure that the calendar and reminder information you display to the user is current.
注冊(cè)通知(Registering for Notifications)
AnEKEventStoreobject posts anEKEventStoreChangedNotificationnotification whenever it detects changes to the Calendar database. Register for this notification if your app handles event or reminder data.
The following code registers for theEKEventStoreChangedNotificationnotification, as shown inListing 5-1.
Listing 5-1?TheEKEventStoreChangedNotificationnotification
[[NSNotificationCenter defaultCenter] addObserver:self
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? selector:@selector(storeChanged:)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? name:EKEventStoreChangedNotification
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? object:eventStore];
響應(yīng)通知(Responding to Notifications)
When you receive anEKEventStoreChangedNotificationnotification, it’s possible that objects you’ve fetched—such as anEKEvent,EKReminder, orEKCalendar, among others—have changed. The effect of these changes depends on whether an event was added, modified, or deleted.
If an event was added, it does not affect any of your previously fetched events or reminders, but the added event may fall within the date range of events you are displaying to the user.
If an event was modified or deleted, properties ofEKEventandEKReminderobjects representing that event may become out of date.
Because your local data is often invalidated or incomplete when a change occurs in the Calendar database, you should refetch your current date range of events whenever you receive anEKEventStoreChangedNotificationnotification. If you are currently modifying an event and you do not want to refetch it unless it is absolutely necessary to do so, you can call therefreshmethod on the event. If the method returnsYES, you can continue to use the event; otherwise, you need to refetch it.
Note:?Events being modified in an event view controller with Event Kit UI for iOS are updated automatically when a change occurs in the Calendar database. For a more in-depth look at Event Kit UI, read the next chapter,“Providing Interfaces for Events.”
提供事件界面(Providing Interfaces for Events)
Important:?The Event Kit UI framework, as referenced by this chapter, is available for iOS only. If you are developing for OS X, you are responsible for constructing your own event view controllers; for more information, read?NSViewController Class Reference.
The Event Kit UI framework provides two types of view controllers for manipulating events:
: use this class if you have an existing event you want to display.
: use this class to allow the user to create, edit, or delete events.
顯示事件數(shù)據(jù)(Displaying Event Data)
To use theEKEventViewControllerclass, you must have an existing event you obtained from an event store. You need to set theeventproperty and any other display options before presenting this type of view controller.Listing 6-1?shows how to create an event view controller and add it to a navigation controller, assumingmyEventalready exists. If you don’t allow the user to edit the event, set theallowsEditingproperty toNO.
Listing 6-1?Editing an existing event
EKEventViewController *eventViewController = [[EKEventViewController alloc] init];
eventViewController.event = myEvent;
eventViewController.allowsEditing = YES;
navigationController = [[UINavigationController alloc] initWithRootViewController:eventViewController];
You need to assign a delegate to an event view controller to receive a notification when the user finishes viewing the event. The delegate conforms to theEKEventViewDelegateprotocol and must implement theeventViewController:didCompleteWithAction:method.
修改事件數(shù)據(jù)(Modifying Event Data)
To allow the user to create, edit, or delete events, use theEKEventEditViewControllerclass and theEKEventEditViewDelegateprotocol. You create an event edit view controller similar to an event view controller, except you must set theeventStoreproperty (setting theeventproperty is optional).
If theeventproperty isnilwhen you present the view controller, the user creates a new event in the default calendar and saves it to the specified event store.
If theeventproperty is notnil, the user edits an existing event. The event must reside in the specified event store—otherwise, an exception is raised.
Instances of theEKEventEditViewControllerclass are designed to be presented modally, as shown inListing 6-2. In this code fragment,selfis the top view controller of a navigation controller. For details on modal view controllers, read“Presenting a View Controller Modally”inView Controller Programming Guide for iOS.
Listing 6-2?Presenting an event edit view controller modally
EKEventEditViewController* controller = [[EKEventEditViewController alloc] init];
controller.eventStore = myEventStore;
controller.editViewDelegate = self;
[self presentModalViewController:controller animated:YES];
You must also specify a delegate to receive notification when the user finishes editing the event. The delegate conforms to theEKEventEditViewDelegateprotocol and must implement theeventEditViewController:didCompleteWithAction:method to dismiss the modal view controller, as shown inListing 6-3. In general, the object that presents a view controller modally is responsible for dismissing it.
Listing 6-3?The delegate dismisses the modal view
- (void)eventEditViewController:(EKEventEditViewController *)controller
? ? ? ? ? didCompleteWithAction:(EKEventEditViewAction)action
{
? ? [self dismissModalViewControllerAnimated:YES];
}
The delegate is also passed the action the user took when finishing the edit. The user can either cancel the changes, save the event, or delete the event. If you need to execute more code after the user dismisses the modal view, implement theeventEditViewController:didCompleteWithAction:delegate method.
文檔修訂歷史(Document Revision History)
This table describes the changes toCalendar and Reminders Programming Guide.
DateNotes
2012-07-17Updated to support OS X Mountain Lion.
2010-09-22Made improvements throughout.
2010-08-03Added a link to the SimpleEKDemo sample code.
2010-04-29New document that explains how to access calendar data in iOS with the Event Kit framework.
轉(zhuǎn)自:http://www.cnblogs.com/xiaobaichangan/p/5160025.html