测试代码

19.0. IntroductionDates, Calendars, and Events

Event Kit and Event Kit UI frameworks 允许你访问日历数据库,你可以插入、读取、修改events。Event Kit UI framework是你能够呈现内置SDKGUI给用户,让用户修改日历数据库。本章我们先专注于Event Kit framework,并学习Event Kit UI framework。

利用Event Kit framework,程序可以偷偷的修改用户的日历数据库。然而这不是好的做法。事实上,苹果公司禁止这样做,他要求我们对日历数据库的任何修改都要通知用户。苹果官方是这么说的:

“如果你的程序需要修改日历数据库,你必须获得用户的许可。应用不应该未在用户的特许下就修改日历数据库”。

iOS有内置日历应用,可以有不同类型的日历。本章中,我们也需要用到不同的日历。为了确保你可以运行本章的代码,你需要创建个iCloud账户,并在手持设备上登陆。

登陆后,可以在日历应用中看到iCloud部分。

为了运行本章代码,你需要引用Event Kit framework,有时候还需要引用Event Kit UI framework,

代码中

#import <EventKit/EventKit.h>

#import <EventKitUI/EventKitUI.h>

iOS模拟器不能模拟日历应用,你需要在真机上测试

本章中得大部分代码专注于读取,处理日历事件。如果你想是使用内置的功能让用户处理日历事件,参看19.10 和19.11

19.1. Requesting Permission to Access Calendars

请求访问许可

调用EKEventStore类的authorizationStatusForEntityType:方法

参数:

EKEntityTypeEvent : 请求访问日历的事件

EKEntityTypeReminder:请求访问日历的提醒

返回值:

EKAuthorizationStatusAuthorized :授权

EKAuthorizationStatusDenied:拒绝

EKAuthorizationStatusNotDetermined :未定

EKAuthorizationStatusRestricted:受限

处于保护用户隐私的需要,在访问事件仓库(event store)时需要获得用户许可也就不奇怪了。实际上,如果你没有先获得用户许可,而去访问日历,iOS将锁定应用的的执行并显示授权提示框。

作为苹果王国上的良好居民,你应该先获得用户的许可再去访问数据,

使用EKEventStore类的requestAccessToEntityType:completion:方法来请求

#pragma mark - Events Kit

-(void)testEKAuthorize

{

EKEventStore *eventStore = [[EKEventStorealloc] init];

switch ([EKEventStoreauthorizationStatusForEntityType:EKEntityTypeEvent]){

caseEKAuthorizationStatusAuthorized:{

[selfextractEventEntityCalendarsOutOfStore:eventStore];

break;

}

caseEKAuthorizationStatusDenied:{

[selfdisplayAccessDenied];

break;

}

caseEKAuthorizationStatusNotDetermined:{

[eventStore requestAccessToEntityType:EKEntityTypeEventcompletion:^(BOOL granted,NSError *error) {

if (granted){

[selfextractEventEntityCalendarsOutOfStore:eventStore];

}else {

[selfdisplayAccessDenied];

}

}];

break;

}

caseEKAuthorizationStatusRestricted:{

[selfdisplayAccessRestricted];

break;

}

}

}

- (void) displayMessage:(NSString *)paramMessage{

UIAlertView *alertView = [[UIAlertViewalloc] initWithTitle:nil

message:paramMessage

delegate:nil

cancelButtonTitle:nil

otherButtonTitles:@"OK",nil];

[alertViewshow];

}

- (void) displayAccessDenied{

[selfdisplayMessage:@"Access to the event store is denied."];

}

- (void) displayAccessRestricted{

[selfdisplayMessage:@"Access to the event store is restricted."];

}

- (void) extractEventEntityCalendarsOutOfStore:(EKEventStore *)paramStore{

NSArray *calendarTypes = @[

@"Local",

@"CalDAV",

@"Exchange",

@"Subscription",

@"Birthday",

];

NSArray *calendars = [paramStorecalendarsForEntityType:EKEntityTypeEvent];

NSUInteger counter = 1;

for (EKCalendar *calendarin calendars){

/* The title of the calendar */

NSLog(@"Calendar %lu Title = %@",

(unsignedlong)counter, calendar.title);

/* The type of the calendar */

NSLog(@"Calendar %lu Type = %@", (unsignedlong)counter,

calendarTypes[calendar.type]);

/* The color that is associated with the calendar */

NSLog(@"Calendar %lu Color = %@", (unsignedlong)counter,

[UIColorcolorWithCGColor:calendar.CGColor]);

/* And whether the calendar can be modified or not */

if ([calendarallowsContentModifications]){

NSLog(@"Calendar %lu can be modified.",  (unsignedlong)counter);

}else {

NSLog(@"Calendar %lu cannot be modified.", (unsignedlong)counter);

}

counter++;

}

}

打印:

2014-07-25 11:12:26.334 cookbook7_19_1[1033:1103] Calendar 1 Title =工作

2014-07-25 11:12:26.338 cookbook7_19_1[1033:1103] Calendar 1 Type = CalDAV

2014-07-25 11:12:26.340 cookbook7_19_1[1033:1103] Calendar 1 Color = UIDeviceRGBColorSpace 0.8 0.45098 0.882353 1

2014-07-25 11:12:26.342 cookbook7_19_1[1033:1103] Calendar 1 can be modified.

2014-07-25 11:12:26.345 cookbook7_19_1[1033:1103] Calendar 2 Title = Birthdays

2014-07-25 11:12:26.348 cookbook7_19_1[1033:1103] Calendar 2 Type = Birthday

2014-07-25 11:12:26.350 cookbook7_19_1[1033:1103] Calendar 2 Color = UIDeviceRGBColorSpace 0.509804 0.584314 0.686275 1

2014-07-25 11:12:26.352 cookbook7_19_1[1033:1103] Calendar 2 cannot be modified.

2014-07-25 11:12:26.353 cookbook7_19_1[1033:1103] Calendar 3 Title =家庭

2014-07-25 11:12:26.355 cookbook7_19_1[1033:1103] Calendar 3 Type = CalDAV

2014-07-25 11:12:26.357 cookbook7_19_1[1033:1103] Calendar 3 Color = UIDeviceRGBColorSpace 0.203922 0.666667 0.862745 1

2014-07-25 11:12:26.359 cookbook7_19_1[1033:1103] Calendar 3 can be modified.

19.2. Retrieving Calendar Groups on an iOS Device

检索日历组

用户有不同的日历账号,比如iCloud账号和其他独立账号

- (void) findIcloudEventSource{

EKSource *icloudEventSource = nil;

EKEventStore *eventStore = [[EKEventStorealloc] init];

for (EKSource *sourcein eventStore.sources){

NSLog(@"source=%@",source);

if (source.sourceType ==EKSourceTypeCalDAV && [source.titlecaseInsensitiveCompare:@"iCloud"]==NSOrderedSame){

icloudEventSource = source;

//            break;

}

}

if (icloudEventSource != nil){

NSLog(@"The iCloud event source was found = %@", icloudEventSource);

NSSet *calendars = [icloudEventSource calendarsForEntityType:EKEntityTypeEvent];

for (EKCalendar *calendarin calendars){

NSLog(@"Calendar = %@", calendar);

}

}else {

NSLog(@"Could not find the iCloud event source");

}

}

2014-07-28 17:02:20.630 cookbook7_19_1[2219:907] source=EKSource <0x1c587c90> {UUID = 912FBAEA-98BD-4865-9CB4-7A827FA6C102; type = CalDAV; title = iCloud; externalId = 912FBAEA-98BD-4865-9CB4-7A827FA6C102}

2014-07-28 17:02:20.636 cookbook7_19_1[2219:907] source=EKSource <0x1c587a70> {UUID = C080AFE7-2C99-4975-863A-04152F585707; type = Local; title = Default; externalId = (null)}

2014-07-28 17:02:20.639 cookbook7_19_1[2219:907] source=EKSource <0x1c587be0> {UUID = C6E67576-3F80-4935-8605-A699743C63FA; type = Other; title = Other; externalId = (null)}

2014-07-28 17:02:20.641 cookbook7_19_1[2219:907] The iCloud event source was found = EKSource <0x1c587c90> {UUID = 912FBAEA-98BD-4865-9CB4-7A827FA6C102; type = CalDAV; title = iCloud; externalId = 912FBAEA-98BD-4865-9CB4-7A827FA6C102}

2014-07-28 17:02:20.648 cookbook7_19_1[2219:907] Calendar = EKCalendar <0x1d0a7a70> {title =工作; type = CalDAV; allowsModify = YES; color = #CC73E1FF;}

2014-07-28 17:02:20.650 cookbook7_19_1[2219:907] Calendar = EKCalendar <0x1c5893d0> {title =家庭; type = CalDAV; allowsModify = YES; color = #34AADCFF;}

打开日历软件看下吧

19.3. Adding Events to Calendars

给日历增加事件

从上一节可以看出,日历应用的iCloud中只有工作和家庭两个Calendar,运行本节代码之前再增加一个名字就叫“calendar”

-(void)testInsertEvent

{

EKEventStore * eventStore = [[EKEventStorealloc] init];

[selfinsertEventIntoStore:eventStore];

}

- (void) insertEventIntoStore:(EKEventStore *)paramStore{

EKSource *icloudSource = [self sourceInEventStore:paramStore

sourceType:EKSourceTypeCalDAV

sourceTitle:@"iCloud"];

if (icloudSource == nil){

NSLog(@"You have not configured iCloud for your device.");

return;

}else{

NSLog(@"icloudSource=%@",icloudSource);

}

EKCalendar *calendar = [self calendarWithTitle:@"Calendar"

type:EKCalendarTypeCalDAV

inSource:icloudSource

forEventType:EKEntityTypeEvent];

if (calendar == nil){

NSLog(@"Could not find the calendar we were looking for.");

return;

}else{

NSLog(@"calendar=%@",calendar);

}

/* The event starts from today, right now */

NSDate *startDate = [NSDate date];

/* And the event ends this time tomorrow.

24 hours, 60 minutes per hour and 60 seconds per minute

hence 24 * 60 * 60 */

NSDate *endDate = [startDate dateByAddingTimeInterval:24 *60 * 60];

/* Create the new event */

BOOL createdSuccessfully = [self createEventWithTitle:@"My Concert"

startDate:startDate

endDate:endDate

inCalendar:calendar

inEventStore:paramStore

notes:nil];

if (createdSuccessfully){

NSLog(@"Successfully created the event.");

}else {

NSLog(@"Failed to create the event.");

}

}

- (BOOL)createEventWithTitle:(NSString *)paramTitle

startDate:(NSDate *)paramStartDate

endDate:(NSDate *)paramEndDate

inCalendar:(EKCalendar *)paramCalendar

inEventStore:(EKEventStore *)paramStore

notes:(NSString *)paramNotes{

BOOL result = NO;

/* If a calendar does not allow modification of its contents

then we cannot insert an event into it */

if (paramCalendar.allowsContentModifications ==NO){

NSLog(@"The selected calendar does not allow modifications.");

return NO;

}

/* Create an event */

EKEvent *event = [EKEvent eventWithEventStore:paramStore];

event.calendar = paramCalendar;

/* Set the properties of the event such as its title,

start date/time, end date/time, etc. */

event.title = paramTitle;

event.notes = paramNotes;

event.startDate = paramStartDate;

event.endDate = paramEndDate;

/* Finally, save the event into the calendar */

NSError *saveError = nil;

result = [paramStoresaveEvent:event

span:EKSpanThisEvent

error:&saveError];

if (result == NO){

NSLog(@"An error occurred = %@", saveError);

}

return result;

}

- (EKSource *) sourceInEventStore:(EKEventStore *)paramEventStore

sourceType:(EKSourceType)paramType

sourceTitle:(NSString *)paramSourceTitle{

for (EKSource *source in paramEventStore.sources){

if (source.sourceType == paramType && [source.titlecaseInsensitiveCompare:paramSourceTitle] == NSOrderedSame){

return source;

}

}

return nil;

}

- (EKCalendar *) calendarWithTitle:(NSString *)paramTitle

type:(EKCalendarType)paramType

inSource:(EKSource *)paramSource

forEventType:(EKEntityType)paramEventType{

for (EKCalendar *calendar in [paramSource calendarsForEntityType:paramEventType]){

if ([calendar.title caseInsensitiveCompare:paramTitle] == NSOrderedSame && calendar.type == paramType){

return calendar;

}

}

return nil;

}

打印:

2014-07-28 17:38:09.590 cookbook7_19_1[2274:907] icloudSource=EKSource <0x208bc910> {UUID = 912FBAEA-98BD-4865-9CB4-7A827FA6C102; type = CalDAV; title = iCloud; externalId = 912FBAEA-98BD-4865-9CB4-7A827FA6C102}

2014-07-28 17:38:09.603 cookbook7_19_1[2274:907] calendar=EKCalendar <0x208beef0> {title = calendar; type = CalDAV; allowsModify = YES; color = #f64f00;}

2014-07-28 17:38:09.665 cookbook7_19_1[2274:907] Successfully created the event.

运行结果表明,calendar的标题不区分大小写。

再到日历应用中看下

19.4. Accessing the Contents of Calendars

检索事件

- (void) readEvents{

/* Instantiate the event store */

EKEventStore *eventStore = [[EKEventStorealloc] init];

EKSource *icloudSource = [self sourceInEventStore:eventStore

sourceType:EKSourceTypeCalDAV

sourceTitle:@"iCloud"];

if (icloudSource == nil){

NSLog(@"You have not configured iCloud for your device.");

return;

}

EKCalendar *calendar = [self calendarWithTitle:@"Calendar"

type:EKCalendarTypeCalDAV

inSource:icloudSource

forEventType:EKEntityTypeEvent];

if (calendar == nil){

NSLog(@"Could not find the calendar we were looking for.");

return;

}

/* The start date will be today */

NSDate *startDate = [NSDate date];

/* The end date will be 1 day from today */

NSDate *endDate = [startDate dateByAddingTimeInterval:24 *60 * 60];

/* Create the predicate that we can later pass to the

event store in order to fetch the events */

NSPredicate *searchPredicate =

[eventStore predicateForEventsWithStartDate:startDate

endDate:endDate

calendars:@[calendar]];

/* Make sure we succeeded in creating the predicate */

if (searchPredicate == nil){

NSLog(@"Could not create the search predicate.");

return;

}

/* Fetch all the events that fall between

the starting and the ending dates */

NSArray *events = [eventStore eventsMatchingPredicate:searchPredicate];

/* Go through all the events and print their information

out to the console */

if (events != nil){

NSUInteger counter = 1;

for (EKEvent *event in events){

NSLog(@"Event %lu Start Date = %@", (unsignedlong)counter,

event.startDate);

NSLog(@"Event %lu End Date = %@", (unsignedlong)counter,

event.endDate);

NSLog(@"Event %lu Title = %@", (unsignedlong)counter,

event.title);

counter++;

}

} else {

NSLog(@"The array of events for this start/end time is nil.");

}

}

打印:

2014-07-28 18:01:30.908 cookbook7_19_1[2296:907] Event 1 Start Date = 2014-07-28 09:38:09 +0000

2014-07-28 18:01:30.910 cookbook7_19_1[2296:907] Event 1 End Date = 2014-07-29 09:38:09 +0000

2014-07-28 18:01:30.912 cookbook7_19_1[2296:907] Event 1 Title = My Concert

19.5. Removing Events from Calendars

删除事件

-(void)testDeleteEvent

{

EKEventStore * eventStore = [[EKEventStorealloc] init];

[selfdeleteEventInStore:eventStore];

}

- (void) deleteEventInStore:(EKEventStore *)paramEventStore{

EKSource *icloudSource = [self sourceInEventStore:paramEventStore

sourceType:EKSourceTypeCalDAV

sourceTitle:@"iCloud"];

if (icloudSource == nil){

NSLog(@"You have not configured iCloud for your device.");

return;

}

EKCalendar *calendar = [self calendarWithTitle:@"Calendar"

type:EKCalendarTypeCalDAV

inSource:icloudSource

forEventType:EKEntityTypeEvent];

if (calendar == nil){

NSLog(@"Could not find the calendar we were looking for.");

return;

}

/* Create the event first */

/* The event starts from today, right now */

NSDate *startDate = [NSDate date];

/* And the event ends this time tomorrow.

24 hours, 60 minutes per hour and 60 seconds per minute

hence 24 * 60 * 60 */

NSDate *endDate = [startDate dateByAddingTimeInterval:24 *60 * 60];

NSString *eventTitle = @"My Event";

BOOL createdSuccessfully = [self createEventWithTitle:eventTitle

startDate:startDate

endDate:endDate

inCalendar:calendar

inEventStore:paramEventStore

notes:nil];

if (createdSuccessfully == NO){

NSLog(@"Could not create the event.");

}

[selfreadEvents];

BOOL removedSuccessfully = [self removeEventWithTitle:eventTitle

startDate:startDate

endDate:endDate

inEventStore:paramEventStore

inCalendar:calendar

notes:nil];

if (removedSuccessfully){

NSLog(@"Successfully created and deleted the event");

} else {

NSLog(@"Failed to delete the event.");

}

}

- (BOOL)removeEventWithTitle:(NSString *)paramTitle

startDate:(NSDate *)paramStartDate

endDate:(NSDate *)paramEndDate

inEventStore:(EKEventStore *)paramEventStore

inCalendar:(EKCalendar *)paramCalendar

notes:(NSString *)paramNotes{

BOOL result = NO;

/* If a calendar does not allow modification of its contents

then we cannot insert an event into it */

if (paramCalendar.allowsContentModifications ==NO){

NSLog(@"The selected calendar does not allow modifications.");

return NO; }

NSPredicate *predicate =  [paramEventStore predicateForEventsWithStartDate:paramStartDate

endDate:paramEndDate

calendars:@[paramCalendar]];

/* Get all the events that match the parameters */

NSArray *events = [paramEventStore eventsMatchingPredicate:predicate];

if ([events count] > 0){

/* Delete them all */

for (EKEvent *event in events){

NSError *removeError = nil;

/* Do not commit here, we will commit in batch after we have

removed all the events that matched our criteria */

if ([paramEventStore removeEvent:event

span:EKSpanThisEvent

commit:NO

error:&removeError] == NO){

NSLog(@"Failed to remove event %@ with error = %@",event, removeError);

}

}

NSError *commitError = nil;

if ([paramEventStore commit:&commitError]){

result =YES;

} else {

NSLog(@"Failed to commit the event store.");

}

} else {

NSLog(@"No events matched your input.");

}

return result;

}

打印:

2014-07-29 10:56:31.337 cookbook7_19_1[2764:907] Event 1 Start Date = 2014-07-29 02:56:31 +0000

2014-07-29 10:56:31.341 cookbook7_19_1[2764:907] Event 1 End Date = 2014-07-30 02:56:31 +0000

2014-07-29 10:56:31.345 cookbook7_19_1[2764:907] Event 1 Title = My Event

2014-07-29 10:56:31.377 cookbook7_19_1[2764:907] Successfully created and deleted the event

19.6. Adding Recurring Events to Calendars

增加循环事件

本例创建一个每月同一天触发的事件

-(void)testCreateRecurringEvent

{

EKEventStore * eventStore = [[EKEventStorealloc] init];

EKSource *icloudSource = [self sourceInEventStore:eventStore

sourceType:EKSourceTypeCalDAV

sourceTitle:@"iCloud"];

if (icloudSource == nil){

NSLog(@"You have not configured iCloud for your device.");

return;

}

EKCalendar *calendar = [self calendarWithTitle:@"Calendar"

type:EKCalendarTypeCalDAV

inSource:icloudSource

forEventType:EKEntityTypeEvent];

if (calendar == nil){

NSLog(@"Could not find the calendar we were looking for.");

return;

}

[selfcreateRecurringEventInStore:eventStore inCalendar:calendar];

}

- (BOOL) createRecurringEventInStore:(EKEventStore *)paramStore inCalendar:(EKCalendar *)paramCalendar{

/* Create an event */

EKEvent *event = [EKEvent eventWithEventStore:paramStore];

/* Create an event that happens today and happens every month for a year from now */

NSDate *eventStartDate = [NSDate date];

/* The event's end date is one hour from the moment it is created */

NSTimeInterval NSOneHour = 1 * 60 * 60;

NSDate *eventEndDate = [eventStartDate dateByAddingTimeInterval:NSOneHour];

/* Assign the required properties, especially

the target calendar */

event.calendar = paramCalendar;

event.title =@"My Event";

event.startDate = eventStartDate;

event.endDate = eventEndDate;

/* The end date of the recurring rule

is one year from now */

NSTimeInterval NSOneYear = 365 * 24 * 60 * 60;

NSDate *oneYearFromNow = [eventStartDate dateByAddingTimeInterval:NSOneYear];

/* Create an Event Kit date from this date */

EKRecurrenceEnd *recurringEnd =[EKRecurrenceEndrecurrenceEndWithEndDate:oneYearFromNow];

/* And the recurring rule. This event happens every

month (EKRecurrenceFrequencyMonthly), once a month (interval:1)

and the recurring rule ends a year from now (end:RecurringEnd) */

EKRecurrenceRule *recurringRule = [[EKRecurrenceRulealloc]

initRecurrenceWithFrequency:EKRecurrenceFrequencyMonthly

interval:1

end:recurringEnd];

/* Set the recurring rule for the event */

event.recurrenceRules =@[recurringRule];

NSError *saveError = nil;

/* Save the event */

if ([paramStoresaveEvent:event span:EKSpanFutureEvents

error:&saveError]){

NSLog(@"Successfully created the recurring event.");

return YES;

} else {

NSLog(@"Failed to create the recurring event %@", saveError);

}

return NO;

}

打印:

2014-07-29 11:28:01.269 cookbook7_19_1[2791:907] Successfully created the recurring event.

19.7. Retrieving the Attendees of an Event

检索时间参与人

-(void)testEnumerateTodayEventsInStore

{

EKEventStore * eventStore = [[EKEventStorealloc] init];

EKSource *icloudSource = [self sourceInEventStore:eventStore

sourceType:EKSourceTypeCalDAV

sourceTitle:@"iCloud"];

if (icloudSource == nil){

NSLog(@"You have not configured iCloud for your device.");

return;

}

EKCalendar *calendar = [self calendarWithTitle:@"Calendar"

type:EKCalendarTypeCalDAV

inSource:icloudSource

forEventType:EKEntityTypeEvent];

if (calendar == nil){

NSLog(@"Could not find the calendar we were looking for.");

return;

}

[selfenumerateTodayEventsInStore:eventStore calendar:calendar];

}

- (void) enumerateTodayEventsInStore:(EKEventStore *)paramStore calendar:(EKCalendar *)paramCalendar{

/* Construct the starting date for today */

NSDate *startDate = [NSDate date];

/* The end date will be 1 day from now */

NSTimeInterval NSOneDay = 1 * 24 * 60 * 60;

NSDate *endDate = [startDate dateByAddingTimeInterval:NSOneDay];

/* Create the predicate that we can later pass to

the event store in order to fetch the events */

NSPredicate *searchPredicate =

[paramStore predicateForEventsWithStartDate:startDate

endDate:endDate

calendars:@[paramCalendar]];

/* Make sure we succeeded in creating the predicate */

if (searchPredicate == nil){

NSLog(@"Could not create the search predicate.");

return;

}

/* Fetch all the events that fall between the

starting and the ending dates */

NSArray *events = [paramStore eventsMatchingPredicate:searchPredicate];

/* Array of NSString equivalents of the values

in the EKParticipantRole enumeration */

NSArray *attendeeRole = @[

@"Unknown",

@"Required",

@"Optional",

@"Chair",

@"Non Participant",

];

/* Array of NSString equivalents of the values

in the EKParticipantStatus enumeration */

NSArray *attendeeStatus = @[

@"Unknown",

@"Pending",

@"Accepted",

@"Declined",

@"Tentative",

@"Delegated",

@"Completed",

@"In Process",

];

/* Array of NSString equivalents of the values

in the EKParticipantType enumeration */

NSArray *attendeeType = @[

@"Unknown",

@"Person",

@"Room",

@"Resource",

@"Group"

];

/* Go through all the events and print their information

out to the console */

if (events != nil){

NSUInteger eventCounter = 0;

for (EKEvent *thisEvent in events){

eventCounter++;

NSLog(@"Event %lu Start Date = %@", (unsignedlong)eventCounter, thisEvent.startDate);

NSLog(@"Event %lu End Date = %@", (unsignedlong)eventCounter, thisEvent.endDate);

NSLog(@"Event %lu Title = %@", (unsignedlong)eventCounter, thisEvent.title);

if (thisEvent.attendees == nil || [thisEvent.attendees count] == 0){

NSLog(@"Event %lu has no attendees", (unsignedlong)eventCounter);

continue;

}

NSUInteger attendeeCounter = 1;

for (EKParticipant *participant in thisEvent.attendees){

NSLog(@"Event %lu Attendee %lu Name = %@", (unsignedlong)eventCounter, (unsignedlong)attendeeCounter, participant.name);

NSLog(@"Event %lu Attendee %lu Role = %@", (unsignedlong)eventCounter,

(unsignedlong)attendeeCounter, attendeeRole[participant.participantRole]);

NSLog(@"Event %lu Attendee %lu Status = %@", (unsignedlong)eventCounter,

(unsignedlong)attendeeCounter, attendeeStatus[participant.participantStatus]);

NSLog(@"Event %lu Attendee %lu Type = %@", (unsignedlong)eventCounter,

(unsignedlong)attendeeCounter, attendeeType[participant.participantType]);

NSLog(@"Event %lu Attendee %lu URL = %@", (unsignedlong)eventCounter, (unsignedlong)attendeeCounter, participant.URL);

attendeeCounter++;

}

}

} else {

NSLog(@"The array of events is nil.");

}

}

打印:

2014-07-29 15:12:54.432 cookbook7_19_1[2899:907] Event 1 Start Date = 2014-07-29 07:12:25 +0000

2014-07-29 15:12:54.435 cookbook7_19_1[2899:907] Event 1 End Date = 2014-07-30 07:12:25 +0000

2014-07-29 15:12:54.437 cookbook7_19_1[2899:907] Event 1 Title = My Concert

2014-07-29 15:12:54.440 cookbook7_19_1[2899:907] Event 1 has no attendees

测试手机,没有联系人的,参与者就不加了

19.8. Adding Alarms to Calendars

增加闹钟

-(void)testAddAlarm

{

EKEventStore * eventStore = [[EKEventStorealloc] init];

EKSource *icloudSource = [self sourceInEventStore:eventStore

sourceType:EKSourceTypeCalDAV

sourceTitle:@"iCloud"];

if (icloudSource == nil){

NSLog(@"You have not configured iCloud for your device.");

return;

}

EKCalendar *calendar = [self calendarWithTitle:@"Calendar"

type:EKCalendarTypeCalDAV

inSource:icloudSource

forEventType:EKEntityTypeEvent];

if (calendar == nil){

NSLog(@"Could not find the calendar we were looking for.");

return;

}

[selfaddAlarmToCalendar:calendar inStore:eventStore];

}

- (void) addAlarmToCalendar:(EKCalendar *)paramCalendar inStore:(EKEventStore *)paramStore{

/* The event starts 60 seconds from now */

NSDate *startDate = [NSDatedateWithTimeIntervalSinceNow:60.0];/* And end the event 20 seconds after its start date */

NSDate *endDate = [startDate dateByAddingTimeInterval:20.0];

EKEvent *eventWithAlarm = [EKEvent eventWithEventStore:paramStore];

eventWithAlarm.calendar = paramCalendar;

eventWithAlarm.startDate = startDate;

eventWithAlarm.endDate = endDate;

/* The alarm goes off 2 seconds before the event happens */

EKAlarm *alarm = [EKAlarmalarmWithRelativeOffset:-2.0];

eventWithAlarm.title =@"Event with Alarm";

[eventWithAlarmaddAlarm:alarm];

NSError *saveError = nil;

if ([paramStore saveEvent:eventWithAlarm

span:EKSpanThisEvent

error:&saveError]){

NSLog(@"Saved an event that fires 60 seconds from now.");

} else {

NSLog(@"Failed to save the event. Error = %@", saveError);

}

}

打印:

2014-07-29 15:27:55.820 cookbook7_19_1[2924:907] Saved an event that fires 60 seconds from now.

19.9. Handling Event Changed Notifications

处理事件改变通知

当用户修改日历数据库内容时,应用得到通知

-(void)testHandleNotificationsInStore

{

EKEventStore * eventStore = [[EKEventStorealloc] init];

EKSource *icloudSource = [self sourceInEventStore:eventStore

sourceType:EKSourceTypeCalDAV

sourceTitle:@"iCloud"];

if (icloudSource == nil){

NSLog(@"You have not configured iCloud for your device.");

return;

}

EKCalendar *calendar = [self calendarWithTitle:@"Calendar"

type:EKCalendarTypeCalDAV

inSource:icloudSource

forEventType:EKEntityTypeEvent];

if (calendar == nil){

NSLog(@"Could not find the calendar we were looking for.");

return;

}

[selfaddAlarmToCalendar:calendar inStore:eventStore];

[selfhandleNotificationsInStore:eventStore];

}

- (void) eventsChanged:(NSNotification *)paramNotification{

NSMutableArray *invalidatedEvents = [[NSMutableArrayalloc] init];

NSLog(@"Refreshing array of events...");

for (EKEvent *event in self.eventsForOneYear){

if ([event refresh] == NO){

[invalidatedEventsaddObject:event];

}

}

if ([invalidatedEvents count] > 0){

[self.eventsForOneYearremoveObjectsInArray:invalidatedEvents];

}

NSLog(@"self.eventsForOneYear=%@",self.eventsForOneYear);

}

- (void) handleNotificationsInStore:(EKEventStore *)paramStore{

EKSource *icloudSource = [selfsourceInEventStore:paramStore

sourceType:EKSourceTypeCalDAV

sourceTitle:@"iCloud"];

if (icloudSource == nil){

NSLog(@"You have not configured iCloud for your device.");

return;

}

EKCalendar *calendar = [selfcalendarWithTitle:@"Calendar"

type:EKCalendarTypeCalDAV

inSource:icloudSource

forEventType:EKEntityTypeEvent];

if (calendar == nil){

NSLog(@"Could not find the calendar we were looking for.");

return;

}

NSTimeInterval NSOneYear =1 * 365 * 24 * 60 * 60;

NSDate *startDate = [NSDatedate];

NSDate *endDate = [startDate dateByAddingTimeInterval:NSOneYear];

NSPredicate *predicate =

[paramStore predicateForEventsWithStartDate:startDate

endDate:endDate

calendars:@[calendar]];

NSArray *events = [paramStore eventsMatchingPredicate:predicate];

self.eventsForOneYear = [[NSMutableArray alloc] initWithArray:events];

NSLog(@"self.eventsForOneYear=%@",self.eventsForOneYear);

[[NSNotificationCenter defaultCenter]addObserver:self

selector:@selector(eventsChanged:)

name:EKEventStoreChangedNotification

object:nil];

}

打印:

2014-07-29 15:53:20.519 cookbook7_19_1[3011:907] Saved an event that fires 60 seconds from now.

2014-07-29 15:53:20.540 cookbook7_19_1[3011:907] self.eventsForOneYear=(

    "EKEvent <0x1cd6dba0> {EKEvent <0x1cd6dba0> {title = Event with Alarm; location = (null); calendar = EKCalendar <0x1cd6bed0> {title = calendar; type = CalDAV; allowsModify = YES; color = #f64f00;}; alarms = (\n    \"EKAlarm <0x1cd6ebf0> {triggerInterval = -2.000000}\"\n); URL = (null); lastModified = 2014-07-29 07:53:20 +0000; timeZone = Asia/Shanghai (GMT+0800) offset 28800}; location = (null); startDate = 2014-07-29 07:54:20 +0000; endDate = 2014-07-29 07:54:40 +0000; allDay = 0; floating = 0; recurrence = (null); attendees = (null)}"

)

没有触发eventsChanged:  这是怎么回事呢?

在应用中获取所有的事件后,切换到日历应用,删除事件,iOS这将广播EKEventStoreChangedNotification消息,你的应用收到消息,可我的例子怎么没触发消息通知呢。关于应用状态以及如何处理消息,请参见相关章节。

19.10. Presenting Event View Controllers 

使用内置的视图控制器显示日历事件

#import "ViewController.h"

#import <EventKit/EventKit.h>

#import <EventKitUI/EventKitUI.h>

@interface ViewController () <EKEventViewDelegate>

@property (nonatomic,strong) EKEventStore *eventStore;

@end

@implementation ViewController

- (void)viewDidLoad

{

[superviewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

}

- (void)didReceiveMemoryWarning

{

[superdidReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

- (void) viewDidAppear:(BOOL)animated{

[superviewDidAppear:animated];

static BOOL beenHereBefore = NO;

if (beenHereBefore){

return;

} else {

beenHereBefore =YES;

}

self.eventStore = [[EKEventStorealloc] init];

switch ([EKEventStoreauthorizationStatusForEntityType:EKEntityTypeEvent]){

caseEKAuthorizationStatusAuthorized:{

[selfdisplayEventViewController];

break;

}

caseEKAuthorizationStatusDenied:{

//            [self displayAccessDenied];

NSLog(@"EKAuthorizationStatusDenied");

break;

}

caseEKAuthorizationStatusNotDetermined:{

[self.eventStorerequestAccessToEntityType:EKEntityTypeEventcompletion:^(BOOL granted,NSError *error) {

if (granted){

[selfdisplayEventViewController];

}else {

//                     [self displayAccessDenied];

NSLog(@"EKAuthorizationStatusDenied");

}

}];

break;

}

caseEKAuthorizationStatusRestricted:{

//            [self displayAccessRestricted];

NSLog(@"EKAuthorizationStatusRestricted");

break;

}

}

}

- (void) displayEventViewController{

EKSource *icloudSource = [self sourceInEventStore:self.eventStore

sourceType:EKSourceTypeCalDAV

sourceTitle:@"iCloud"];

if (icloudSource == nil){

NSLog(@"You have not configured iCloud for your device.");

return;

}

NSSet *calendars = [icloudSourcecalendarsForEntityType:EKEntityTypeEvent];

NSTimeInterval NSOneYear = 1 * 365 * 24.0f * 60.0f * 60.0f;

NSDate *startDate = [[NSDate date] dateByAddingTimeInterval:-NSOneYear];

NSDate *endDate = [NSDate date];

NSPredicate *predicate =

[self.eventStorepredicateForEventsWithStartDate:startDate

endDate:endDate

calendars:calendars.allObjects];

NSArray *events = [self.eventStoreeventsMatchingPredicate:predicate];

if ([events count] > 0){

EKEvent *event = events[0];

EKEventViewController *controller = [[EKEventViewControlleralloc] init];

controller.event = event;

controller.allowsEditing =YES;

controller.allowsCalendarPreview =YES;

controller.delegate =self;

self.navigationItem.backBarButtonItem =

[[UIBarButtonItemalloc] initWithTitle:@"Go Back"

style:UIBarButtonItemStylePlain

target:nil

action:nil];

//        [self.navigationController pushViewController:controller

//                                             animated:YES];

[selfpresentViewController:controller animated:YEScompletion:nil];

}

}

- (void)eventViewController:(EKEventViewController *)controller didCompleteWithAction:(EKEventViewAction)action{

switch (action){

caseEKEventViewActionDeleted:{

NSLog(@"User deleted the event.");

break;

}

caseEKEventViewActionDone:{

NSLog(@"User finished viewing the event.");

break;

}

caseEKEventViewActionResponded:{

NSLog(@"User responsed to the invitation in the event.");

break;

}

}

}

- (EKSource *) sourceInEventStore:(EKEventStore *)paramEventStore

sourceType:(EKSourceType)paramType

sourceTitle:(NSString *)paramSourceTitle{

for (EKSource *source in paramEventStore.sources){

if (source.sourceType == paramType && [source.titlecaseInsensitiveCompare:paramSourceTitle] == NSOrderedSame){

return source;

}

}

return nil;

}

@end

19.11. Presenting Event Edit View Controllers

使用内置事件编辑器让用户在你的程序里编辑事件

#import "ViewController0.h"

#import <EventKitUI/EventKitUI.h>

#import <EventKit/EventKit.h>

@interface ViewController0 ()<EKEventEditViewDelegate>

@property (nonatomic,strong) EKEventStore *eventStore;

- (IBAction)buttonAction:(id)sender;

@end

@implementation ViewController0

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

{

self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

if (self) {

// Custom initialization

}

return self;

}

- (void)viewDidLoad

{

[superviewDidLoad];

// Do any additional setup after loading the view.

self.eventStore = [[EKEventStorealloc] init];

}

- (void)didReceiveMemoryWarning

{

[superdidReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

- (void)eventEditViewController:(EKEventEditViewController *)controller

didCompleteWithAction:(EKEventEditViewAction)action{

switch (action){

caseEKEventEditViewActionCanceled:{

NSLog(@"Cancelled");

break;

}

caseEKEventEditViewActionSaved:{

NSLog(@"Saved");

break; }

caseEKEventEditViewActionDeleted:{

NSLog(@"Deleted");

break;

}

}

//    [self.navigationController dismissViewControllerAnimated:YES

//                                                  completion:nil];

[selfdismissViewControllerAnimated:YEScompletion:nil];

}

- (void) displayEventEditController{

EKSource *icloudSource = [self sourceInEventStore:self.eventStore

sourceType:EKSourceTypeCalDAV

sourceTitle:@"iCloud"];

if (icloudSource == nil){

NSLog(@"You have not configured iCloud for your device.");

return;

}

NSSet *calendars = [icloudSourcecalendarsForEntityType:EKEntityTypeEvent];

NSTimeInterval NSOneYear = 1 * 365 * 24.0f * 60.0f * 60.0f;

NSDate *startDate = [[NSDate date] dateByAddingTimeInterval:-NSOneYear];

NSDate *endDate = [NSDate date];

NSPredicate *predicate =

[self.eventStorepredicateForEventsWithStartDate:startDate

endDate:endDate

calendars:calendars.allObjects];

NSArray *events = [self.eventStoreeventsMatchingPredicate:predicate];

if ([events count] > 0){

EKEvent *event = events[0];

EKEventEditViewController *controller = [[EKEventEditViewControlleralloc] init];

controller.event = event;

controller.editViewDelegate =self;

//        [self.navigationController presentViewController:controller

//                                                animated:YES

//                                              completion:nil];

[selfpresentViewController:controller

animated:YES

completion:nil];

}

}

- (EKSource *) sourceInEventStore:(EKEventStore *)paramEventStore

sourceType:(EKSourceType)paramType

sourceTitle:(NSString *)paramSourceTitle{

for (EKSource *source in paramEventStore.sources){

if (source.sourceType == paramType && [source.titlecaseInsensitiveCompare:paramSourceTitle] == NSOrderedSame){

return source;

}

}

return nil;

}

- (IBAction)buttonAction:(id)sender {

[selfdisplayEventEditController];

}

@end

打印:

2014-07-29 17:13:57.789 cookbook7_19_1[3226:907] Cancelled

2014-07-29 17:14:01.988 cookbook7_19_1[3226:907] Cancelled

2014-07-29 17:14:16.393 cookbook7_19_1[3226:907] Calendar: unable to save: (null)

2014-07-29 17:14:22.549 cookbook7_19_1[3226:907] Remove failed: (null)

2014-07-29 17:14:22.551 cookbook7_19_1[3226:907] Deleted

修改不了,是不是没权限呢,嗨。。。

19.0~19.11 Dates, Calendars, and Events 日历事件的处理相关推荐

  1. Greenplum【部署 07】6.19.0详细安装步骤libnsl/libcrypto/libssl/libreadline No such file or directory 问题解决

    问题解决所需文件网盘资源: 链接:https://pan.baidu.com/s/1uMrhVmHlvEQ-sEGZtqhqiw 提取码:kkab 文件列表: libnsl-2.17.so libcr ...

  2. MySql8.0.19最新版本创建用户分配权限演示,You have an error in your SQL syntax权限分配问题解决方法

    MySql 8.0.19 权限分配 问题一:You have an error in your SQL syntax ---语法问题 问题二:You are not allowed to create ...

  3. mysql压缩包安装教程8.0.19,win10安装zip版MySQL8.0.19的教程详解

    win10安装zip版MySQL8.0.19的教程详解 一. 下载后解压到想安装的目录 二. 在安装目录中添加配置文件my.ini [mysqld] # 设置3306端口 port=3306 # 设置 ...

  4. mysql+installer+community+5.7.9_win10系统,mysql-installer-community-5.7.19.0.msi安装

    1.进入官网找到自己所需的安装包:https://dev.mysql.com/  ,路径:DOWNLOAD-->MYSQL Community Edition(GRL)-->MYSQL o ...

  5. python msi installer_Windows10 MYSQL Installer 安装(mysql-installer-community-5.7.19.0.msi)

    1.进入官网找到自己所需的安装包:https://dev.mysql.com/  ,路径:DOWNLOAD-->MYSQL Community Edition(GRL)-->MYSQL o ...

  6. /^(0|[1-9]\d*)([.]5)?$/ 在PHP正则中是什么意思 ?

    1 ^以什么开头 2 ()分组 3 |或的意思 4 \d 匹配任何数字字符串 [0-9] 5 0|[1-9]\d* 0 或1-9之间的数+任意数字零次或多次 开头 6 ()分组 7 []原子表 8 [ ...

  7. mysql8.0日期类型_mysql8.0.19基础数据类型详解

    mysql基础数据类型 mysql常用数据类型概览 ![1036857-20170801181433755-146301178](D:\笔记\mysql\复习\1036857-201708011814 ...

  8. Ubuntu20.10系统FreeCAD 0.19编译安装

    Ubuntu20.10系统FreeCAD 0.19编译安装 济南友泉软件有限公司 零.系统环境 root@test-HVM-domU:~# lsb_release -a No LSB modules ...

  9. mysql安装包msi_win10系统,mysql-installer-community-5.7.19.0.msi安装

    1.进入官网找到自己所需的安装包:https://dev.mysql.com/  ,路径:DOWNLOAD-->MYSQL Community Edition(GRL)-->MYSQL o ...

最新文章

  1. OpenCV图像处理使用笔记(四)——图像融合
  2. 按键精灵 getcursorpos没有用_给你们想要的一键输出II按键精灵脚本开发教程
  3. boost::advance用法的测试程序
  4. [css] 说说你对GPU的理解,举例说明哪些元素能触发GPU硬件加速?
  5. 斯坦福-随机图模型-week4.0_
  6. 用Canvas为网页加入动态背景
  7. ES6 知识点及常考面试题
  8. DP+BIT(优化复杂度) UESTC 1217 The Battle of Chibi
  9. 解决「matplotlib 图例中文乱码」问题
  10. 第二期!团队开发spring会议~day8
  11. 图论算法——加权无向图的数据结构
  12. C语言多线程基础-01-线程的创建与销毁
  13. 简述springmvc过程_Springmvc执行流程
  14. 红帽学习笔记[RHCSA] 第三课[输出重定向、Vi编辑器]
  15. python包的init文件_Python模块包中__init__.py文件的作用
  16. 测试象棋水平用哪个软件好,佳佳象棋软件作者李国来对象棋软件引擎的专业看法及测试指导...
  17. VMWare虚拟机Linux系统忘记登录密码
  18. ISO27001(BS7799/ISO17799)国标
  19. 关于电脑分屏截图问题
  20. 玩游戏计算机虚拟内存怎么设置,【新手指导】电脑虚拟内存设置

热门文章

  1. 论文笔记:Universal Adversarial Triggers for Attacking and Analyzing NLP
  2. java纯真ip数据库_java实现对纯真IP数据库的查询
  3. html visibility属性,CSS属性参考 | visibility
  4. C++ 操作Excel
  5. 2021高考辽宁英语成绩查询,2021年辽宁高考英语满分多少分?
  6. Melanopic EDI(简称m-EDI) 计算软件
  7. Java--贪吃蛇日志
  8. 什么是机器语言、汇编语言、高级语言?
  9. javascript设计模式-观察者模式(observer pattern)
  10. 《小王子》精彩章节——Chapter 21