现在的位置: 首页 > 综合 > 正文

[iOS]日历和提醒编程指南(Calendar and Reminders Programming Guide)

2013年02月03日 ⁄ 综合 ⁄ 共 9043字 ⁄ 字号 评论关闭
分析:事件提醒开发包(EventKit)由事件库、事件源、日历和事件/提醒组成,他们的关系是:事件库用于直接操作日历数据库,日历数据库中的数据按事件源、日历和事件/提醒三级进行分类组织。每个事件源对应一个准帐户,该帐户下可以有多个日历,日历分两类,一类是用于存储事件的日历,一类是用于存储提醒的日历。这里所说的存储,实际就是分类,反过来的,根据子项对父项进行分类。就如两口缸,一口装水,一口沙子一样,这个缸就是上面提及的日历,水相当于事件,沙子相当于提醒。一户人家的院子里可以摆好多口缸,这个院子就相当于帐户,有两个默认帐户,一个是Local,一个是Other。帐户的类型,还可能有iCloud或Gmail帐号等,一般是邮箱附带的,所以就默认对应着该邮箱地址了。就像
大户人家的总管,管好每户的院子,还有每个院子里的缸一样,事件库直接管理所有的帐户和日历,还有日历下的事件或提醒。管理包括增加、修改、查询、删除(CURD)。
  • 日历和提醒入门(Introduction to Calendars and Reminders) 

事件库框架授权访问用户的 Calendar.app 和 Reminders.app 应用的信息。尽管是用两个不同的应用显示用户的日历和提醒数据,但确是同一个框架维护这份数据。同样地,存储这份数据的数据库叫做日历数据库,同时容纳日历和提醒信息。

The Event Kit framework grants access to users’ Calendar.app and Reminders.app information.
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 the 
EKEventStore class.
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 the 
EKEvent class.
Likewise, you can modify its calendar 
information by setting the properties of the EKEvent class.
 
 

    • 连接到事件库(Connecting to the Event Store)    

在 iOS 5 及以后版本系统中,使用默认的初始化器:

On iOS 5 and later, initialize an EKEventStore object
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 the requestAccessToEntityType: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 an EKEventStore object with the designated initializer initWithAccessToEntityTypes::

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 对象需要相对较大量的时间来初始化和释放。因此,你不应该为每一个事件相关的任务都初始化和释放事件库。相反,在你的应用加载时,初始化一个事件库,然后反复地使用这一个来确保连接一直可用。

事件库实例不应该在其它事件开发包相对的对象释放前被释放,否则可能发生意想不到的状态。

An EKEventStore object 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 of  
EKEvent objects
by date, call 
sortedArrayUsingSelector: on
the array, providing the selector for the 
compareStartDateWithEvent: method.

      • 使用谓词(Using Predicates ) 

通常是要获得属于某一日期范围的事件。 EKEventStore
 eventsMatchingPredicate: 方法获取属于你提供的谓词中指定的日期范围的所有事件。

It’s common to fetch events that fall within a date range. The EKEventStore method eventsMatchingPredicate: 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
the  
eventsMatchingPredicate: method accepts a parameter of type NSPredicate,
you must supply a predicate created with the 
EKEventStore method predicateForEventsWithStartDate: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 of EKCalendar objects
as the 
calendars parameter of the predicateForEventsWithStartDate:endDate:calendars: method.
You can get the user’s calendars from the event store’s 
calendarsForEntityType: method.
Passing 
nil tells the method to fetch from all of the user’s calendars.

因为方法  eventsMatchingPredicate: 是同步的,而你可能并不想在你的应用主线程中运行它。如果要异步执行的话,那么使用 dispatch_async 函数或使用一个 NSOperation 对象,就可以在另一个线程中运行该方法了。

Because the 

抱歉!评论已关闭.