#import
- (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) {
//错误细心
// display error message here
}
else if (!granted) {
//被用户拒绝,不允许访问日历
// display access denied error message here
} else{
// access granted
// ***** do the important stuff here *****
//事件保存到日历
//创建事件
EKEvent *event = [EKEvent eventWithEventStore:eventStore];
event.title = @"哈哈哈,我是日历事件啊";
event.location = @"我在杭州西湖区留和路";
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 = @"我在杭州西湖区留和路";
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(@"保存成功");
}
}
分析:事件提醒开发包(EventKit)由事件库、事件源、日历和事件/提醒组成,他们的关系是:事件库用于直接操作日历数据库,日历数据库中的数据按事件源、日历和事件/提醒三级进行分类组织。每个事件源对应一个准帐户,该帐户下可以有多个日历,日历分两类,一类是用于存储事件的日历,一类是用于存储提醒的日历。这里所说的存储,实际就是分类,反过来的,根据子项对父项进行分类。就如两口缸,一口装水,一口沙子一样,这个缸就是上面提及的日历,水相当于事件,沙子相当于提醒。一户人家的院子里可以摆好多口缸,这个院子就相当于帐户,有两个默认帐户,一个是Local,一个是Other。帐户的类型,还可能有iCloud或Gmail帐号等,一般是邮箱附带的,所以就默认对应着该邮箱地址了。就像 大户人家的总管,管好每户的院子,还有每个院子里的缸一样,事件库直接管理所有的帐户和日历,还有日历下的事件或提醒。管理包括增加、修改、查询、删除(CURD)。
日历和提醒入门(Introduction to Calendars and Reminders)
事件库框架授权访问用户的Calendar.app和Reminders.app 应用的信息。尽管是用两个不同的应用显示用户的日历和提醒数据,但确是同一个框架维护这份数据。同样地,存储这份数据的数据库叫做日历数据库,同时容纳日历和提醒信息。
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 事件库结构 Figure I-1 Event Kit architecture
事件库不但允许你的应用获取用户已经存在的日历及提醒数据,而且它可以让你的应用为任何日历创建新的事件和提醒。另外,事件库让用户可以编辑和删除他们的事件和提醒(整体叫做“日历项”)。更高级的任务,诸如添加闹钟或指定循环事件,也可以使用事件库完成。如果日历数据库有来自你的应用外部的更改发生,事件库可以通过通知监测到,这样你的应用可以做出适当的响应。使用事件库对日历项所做的更改会自动地同步到相关的日历(CalDAV - 是一种效率手册同步协议,有些效率手册 如 Apple iCal、Mozilla Lightning/Sunbird 使用这一协议使其信息能与其它效率手册 如 Yahoo! 效率手册 进行交换;Exchange 等)。
本文档描述事件库的概念及通用的编程任务。如果你想要从你的应用来显示或编辑日历事件和/或提醒数据,那么你应该阅读本文档。事件库提供了有限的对用户日历数据库的访问;但它并未包含期望实现完整特性的日历或提醒应用所需的每一个功能,诸如出席者和帐户。
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)
本文档包含如下几章,这些内容描述了如何在你的应用内集成用户的日历和提醒数据:
“读写日历事件” 描述了如何获取、创建和修改日历事件。
“读写提醒” 描述了如何获取、创建和修改提醒。
“配置闹钟” 描述了如何附加闹钟到一个日历项。
“创建循环的事件” 描述了如何使一个事件变成循环事件。
“监视日历数据库的外部更改” 描述了如何注册通知以关注日历数据库的外部更改。
“提供事件界面” 描述了如何显示事件视图控制器以允许你的用户来创建和编辑事件。
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)
本文档是下面的示例代码和参考手册的配套指南:
SimpleEKDemo是一个使用事件库中事件的示例代码工程。
Event Kit Framework Reference提供了一个事件库 API 的较深入的描述,这些 API 就是一个访问用户的日历数据库的框架。
Event Kit UI Framework Reference详细说明了事件库用户界面的 API,就是一个 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类从用户的日历数据库中获取、创建、编辑和删除事件。你可以获取匹配你提供的谓词的事件自定义的一组事件,或通过唯一标识获取一个单独的事件。你获取到一个事件后,可以使用EKEvent类的属性获取访问该事件相关的日历信息。同样的,你可以通过设置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 及以后版本系统中,使用默认的初始化器:
On iOS 5 and later, initialize anEKEventStoreobject with the default initializer:
EKEventStore *store = [[EKEventStore alloc] init];
在 iOS 6 及以后版本,你必须在事件库初始化后,使用requestAccessToEntityType:completion:方法请求使用用户的日历数据库。请求访问某个实体类型会异步提示用户允许或禁止你的应用使用他们的日历信息。你应该处理用户授权或禁止你的应用访问权的各种状况:
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对象需要相对较大量的时间来初始化和释放。因此,你不应该为每一个事件相关的任务都初始化和释放事件库。相反,在你的应用加载时,初始化一个事件库,然后反复地使用这一个来确保连接一直可用。
事件库实例不应该在其它事件开发包相对的对象释放前被释放,否则可能发生意想不到的状态。
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)
有两种方式获取事件。通过谓词或搜索查询获取,会返回零个或多个与给定查询匹配的事件。通过唯一标识获取会返回与给定标识相符的唯一的一个事件。
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.
注意:从日历数据库获取事件并不一定按时间顺序返回。要通过日期排序EKEvent对象的数组,可以在数组上调用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 展示了如何获取发生在一天前和当前之后一年之内的所有事件。
Listing 1-1 demonstrates how to fetch all events that occur between one day before and one year after the current date.
注意:尽管eventsMatchingPredicate:方法接受一个NSPredicate类型的参数,但你必须提供一个用EKEventStore的方法predicateForEventsWithStartDate:endDate:calendars:创建的谓词。
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
// 获取适当的日期(Get the appropriate calendar)
NSCalendar *calendar = [NSCalendar currentCalendar];
// 创建起始日期组件(Create the start date components)
NSDateComponents *oneDayAgoComponents = [[NSDateComponents alloc] init];
oneDayAgoComponents.day = -1;
NSDate *oneDayAgo = [calendar dateByAddingComponents:oneDayAgoComponents
toDate:[NSDate date]
options:0];
// 创建结束日期组件(Create the end date components)
NSDateComponents *oneYearFromNowComponents = [[NSDateComponents alloc] init];
oneYearFromNowComponents.year = 1;
NSDate *oneYearFromNow = [calendar dateByAddingComponents:oneYearFromNowComponents
toDate:[NSDate date]
options:0];
// 用事件库的实例方法创建谓词 (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];
你可以指定一个日历的子集来搜索,这需要传递一个EKCalendar对象的数组作为predicateForEventsWithStartDate:endDate:calendars:方法的calendars参数。你可以从事件库的calendarsForEntityType:方法获得用户的不同类型的日历。如果传一个 nil 值,那么就是告诉这个方法获取用户的所有日历。
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.
因为方法eventsMatchingPredicate:是同步的,而你可能并不想在你的应用主线程中运行它。如果要异步执行的话,那么使用dispatch_async函数或使用一个NSOperation对象,就可以在另一个线程中运行该方法了。
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.
使用唯一标识(Using Unique Identifiers )
如果你之前使用谓词获得了一个事件并知道它的唯一标识,那么你可以使用EKEventStore的eventWithIdentifier:方法来再次获取该事件。如果它是一个循环事件,那么这个方法就会返回第一次出现的该事件。你可以使用属性eventIdentifier获得事件的唯一标识。
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.
创建及编辑事件(Creating and Editing Events)
注意:如果你正在 iOS上开发,那么你可以选择使用事件库用户界面框架提供的事件视图控制器来让用户修改事件数据。有关如何使用这些事件视图控制器的信息,参见“为事件提供界面。”
使用 事件EKEvent的eventWithEventStore:方法创建一个新的事件。
你可以通过设置一个新的事件或先前从日历数据库获取的事件的对应属性来编辑事件。你可以编辑的详细内容包括:
事件的标题用title属性
事件的起始日期用startDate和endDate属性
与事件关联的日历用属性calendar
与事件相关的闹钟用alarms属性 (参见“配置闹钟”以获得更多详细信息)
如果一个事件是循环事件,那么它的循环规则用属性recurrenceRules(参见“创建循环事件”以获得更多详细信息)
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)
提示:如果你的应用修改用户的日历数据库,它必须在这之前先从用户获得确认。应用在未得到用户的特定指示的情况下决不可能修改日历数据库。
你对事件的修改不是持久化的,直到你保存它们为止。使用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 会立即持久保存更改)。
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.
执行批量事件操作(Performing Batch Operations on Events)
你可以在EKEventStore的enumerateEventsMatchingPredicate:usingBlock:方法执行给定的谓词匹配的所有事件上执行同一个操作。你必须为上述方法使用EKEventStore的predicateForEventsWithStartDate:endDate:calendars:方法创建谓词。你提供的操作是 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);
块接收两个参数(The block is passed two parameters):
event
当前被操作的事件(The event that is currently being operated on).
stop
一个布尔值,它决定当前块返回后enumerateEventsMatchingPredicate:usingBlock:方法是否应该停止继续处理事件。如果是 YES,那么与该谓词匹配的任何未处理的事件仍保持未处理状态。
提示:记住,使用该方法会引起对用户的日历数据库的有效的修改。确认在你向用户请求批准时,让用户清楚地知道你所要执行的操作。
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)
提醒就是一些可以关联到特定时间或位置的任务。他们与日历事件很相似,但可以被标识为完成并且可以不必跨跃一段确切的时间。
因为EKReminder继承自EKCalendarItem,所以你可以在提醒上执行与在事件上一样的方法,诸如使用addAlarm:方法添加一个闹钟,或使用addRecurrenceRule:方法设置一个循环规则。
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 上初始访问提醒的连接,传递的参数不是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:请求对用户日历数据库的访问权。请求某一实体类型的访问权会提示用户允许或禁止你的应用使用日历信息。你应该处理用户授权或禁止访问每种情况:
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 上你不需要请求用户提醒的访问权,因为访问权是默认授予的(译者注:iOS 模拟器上也是默认授予的)。
正如搜索事件一样,也有两种途径来获取提醒。
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)
你可以调用fetchRemindersMatchingPredicate:completion:方法来访问与某一谓词匹配的多个提醒。传递的谓词可通过如下方法得到:
predicateForIncompleteRemindersWithDueDateStarting:ending:calendars:
找到(指定的日历中)在某一选定的时间段内所有未完成的提醒
predicateForCompletedRemindersWithCompletionDateStarting:ending:calendars:
找到(指定的日历中)某一选定的时间段内所有完成的提醒
predicateForRemindersInCalendars:
找到(指定的日历中)所有提醒
你可以给 completion 参数传一个块来迭代所有匹配的提醒,如列表 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
}
}];
注意:不像通过谓词获取事件那样(参见“使用谓词”),你可以通过谓词异步获取提醒,而无需分派到其它线程。
如果你想要中止通过谓词获取的请求,可以调用cancelFetchRequest:方法并传递之前由fetchRemindersMatchingPredicate:completion:方法返回的标识。
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:.
使用唯一标识(Using Unique Identifiers)
如果你知道一个从先前用谓词获取到的提醒的唯一标识,那么你可以调用calendarItemWithIdentifier:实例方法,该方法可以获取到任何与该标识符匹配的日历项(提醒或事件),而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.
创建及编辑提醒(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.
设置地理围栏(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.
创建循环事件(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.
使用基本规则(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.
使用复杂的规则(Using Complex Rules)
You can create a recurrence rule with a complex pattern using the
initRecurrenceWithFrequency:interval:daysOfTheWeek:daysOfTheMonth:monthsOfTheYear:weeksOfTheYear:daysOfTheYear:setPositions:end:
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.
监视日历数据库的外部更改(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.
注册通知(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];
响应通知(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:
EKEventViewController
: use this class if you have an existing event you want to display.
EKEventEditViewController
: use this class to allow the user to create, edit, or delete events.
显示事件数据(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.
修改事件数据(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.
转自:http://www.cnblogs.com/xiaobaichangan/p/5160025.html