19.0~19.11 Dates, Calendars, and Events 日历事件的处理
测试代码
19.0. Introduction(Dates, 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 日历事件的处理相关推荐
- 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 ...
- 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 ...
- mysql压缩包安装教程8.0.19,win10安装zip版MySQL8.0.19的教程详解
win10安装zip版MySQL8.0.19的教程详解 一. 下载后解压到想安装的目录 二. 在安装目录中添加配置文件my.ini [mysqld] # 设置3306端口 port=3306 # 设置 ...
- 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 ...
- 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 ...
- /^(0|[1-9]\d*)([.]5)?$/ 在PHP正则中是什么意思 ?
1 ^以什么开头 2 ()分组 3 |或的意思 4 \d 匹配任何数字字符串 [0-9] 5 0|[1-9]\d* 0 或1-9之间的数+任意数字零次或多次 开头 6 ()分组 7 []原子表 8 [ ...
- mysql8.0日期类型_mysql8.0.19基础数据类型详解
mysql基础数据类型 mysql常用数据类型概览 ![1036857-20170801181433755-146301178](D:\笔记\mysql\复习\1036857-201708011814 ...
- Ubuntu20.10系统FreeCAD 0.19编译安装
Ubuntu20.10系统FreeCAD 0.19编译安装 济南友泉软件有限公司 零.系统环境 root@test-HVM-domU:~# lsb_release -a No LSB modules ...
- mysql安装包msi_win10系统,mysql-installer-community-5.7.19.0.msi安装
1.进入官网找到自己所需的安装包:https://dev.mysql.com/ ,路径:DOWNLOAD-->MYSQL Community Edition(GRL)-->MYSQL o ...
最新文章
- OpenCV图像处理使用笔记(四)——图像融合
- 按键精灵 getcursorpos没有用_给你们想要的一键输出II按键精灵脚本开发教程
- boost::advance用法的测试程序
- [css] 说说你对GPU的理解,举例说明哪些元素能触发GPU硬件加速?
- 斯坦福-随机图模型-week4.0_
- 用Canvas为网页加入动态背景
- ES6 知识点及常考面试题
- DP+BIT(优化复杂度) UESTC 1217 The Battle of Chibi
- 解决「matplotlib 图例中文乱码」问题
- 第二期!团队开发spring会议~day8
- 图论算法——加权无向图的数据结构
- C语言多线程基础-01-线程的创建与销毁
- 简述springmvc过程_Springmvc执行流程
- 红帽学习笔记[RHCSA] 第三课[输出重定向、Vi编辑器]
- python包的init文件_Python模块包中__init__.py文件的作用
- 测试象棋水平用哪个软件好,佳佳象棋软件作者李国来对象棋软件引擎的专业看法及测试指导...
- VMWare虚拟机Linux系统忘记登录密码
- ISO27001(BS7799/ISO17799)国标
- 关于电脑分屏截图问题
- 玩游戏计算机虚拟内存怎么设置,【新手指导】电脑虚拟内存设置
热门文章
- 论文笔记:Universal Adversarial Triggers for Attacking and Analyzing NLP
- java纯真ip数据库_java实现对纯真IP数据库的查询
- html visibility属性,CSS属性参考 | visibility
- C++ 操作Excel
- 2021高考辽宁英语成绩查询,2021年辽宁高考英语满分多少分?
- Melanopic EDI(简称m-EDI) 计算软件
- Java--贪吃蛇日志
- 什么是机器语言、汇编语言、高级语言?
- javascript设计模式-观察者模式(observer pattern)
- 《小王子》精彩章节——Chapter 21