EventKit:创建、查看、编辑日历
和提醒事件
.
苹果文档
- https://developer.apple.com/library/archive/documentation/DataManagement/Conceptual/EventKitProgGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40004759-SW1
- https://developer.apple.com/documentation/eventkit?language=objc
EKEventStore
-
eventStoreIdentifier
:如果store被损坏,会产生一个新的eventStoreIdentifier.
//EventStore类似数据库, 频繁访问, 使用一个单例
- (EKEventStore *)sharedEKEventStore
{
static EKEventStore *eventStore = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
eventStore = [[EKEventStore alloc] init];
});
return eventStore;
}
Searching Calendars
主要两种方法:
方法一:根据日历的时间、标题等这些属性,根据EKEventStore中的日历事件,找到相同的事件。
- enumerateEventsMatchingPredicate:usingBlock:
- eventsMatchingPredicate:
- fetchRemindersMatchingPredicate:completion:
predicate必须使用下面的Predicate
创造, 苹果文档明确给出了注释.
方法二:根据EKEvent
的eventIdentifier
EKEvent的唯一标识.
需要保存在服务器根据设备ID,不能放在本地.比如:用户卸载后又重新安装的情况.
建议:在查询的时候,最好两个方法结合,优先使用EKEvent
的eventIdentifier
, App本地保存一份eventIdentifier,如果本地没有的话再使用Predicate.
//查询事件
-(EKEvent *)queryEKEventForIdentifierKey:(NSString *)calendarIdentifierKey{
EKAuthorizationStatus authorizationStatus = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
if (authorizationStatus != EKAuthorizationStatusAuthorized) {
return nil;
}
//只有授权后才能访问
//优先使用本地缓存的eventIdentifier做判断.
NSString *identifier = [[NSUserDefaults standardUserDefaults] stringForKey:calendarIdentifierKey];
if (identifier && identifier.length>0) {
EKEvent *event = [[self sharedEKEventStore] eventWithIdentifier:identifier];
return event;
}
///使用predicent: 查询的是从现在到后面1年
NSCalendar *calendar = [NSCalendar currentCalendar];
// Create the start date components: 从今天0:0开始
NSDateComponents *nowdateComponents = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
NSDateComponents *startDateComponents = [[NSDateComponents alloc] init];
[startDateComponents setDay:nowdateComponents.day];
[startDateComponents setMonth:nowdateComponents.month];
[startDateComponents setYear:nowdateComponents.year];
[startDateComponents setHour:0];
[startDateComponents setMinute:0];
NSDate *startDate = [calendar dateFromComponents:startDateComponents];
// Create the end date components
NSDateComponents *oneYearFromNowComponents = [[NSDateComponents alloc] init];
oneYearFromNowComponents.year = 1;
NSDate *oneYearFromNow = [calendar dateByAddingComponents:oneYearFromNowComponents
toDate:[NSDate date]
options:0];
EKCalendar *tempCalendar = [[self sharedEKEventStore] defaultCalendarForNewEvents];
NSMutableArray *calendars = [NSMutableArray array];
if (!tempCalendar) {
calendars = nil;
}else{
[calendars addObject:tempCalendar];
}
NSPredicate *predicate = [[self sharedEKEventStore] predicateForEventsWithStartDate:startDate endDate:oneYearFromNow calendars:calendars];
NSArray *events = [[self sharedEKEventStore] eventsMatchingPredicate:predicate];
EKEvent *resultEvent = nil;
if (events && [events isKindOfClass:[NSArray class]] && events.count>0) {
for (EKEvent *event in events) {
if ([event.title rangeOfString:@"六六大顺"].location != NSNotFound &&
[event.title rangeOfString:@"签到"].location != NSNotFound) {
resultEvent = event;
break;
}
}
}
return resultEvent;
}
Predicate
- predicateForEventsWithStartDate:endDate:calendars:
- predicateForRemindersInCalendars:
- predicateForCompletedRemindersWithCompletionDateStarting:ending:calendars:
- predicateForIncompleteRemindersWithDueDateStarting:ending:calendars:
EKEvent相关属性
URL
用来给日历事件添加URL, 一般用“unlink/schema/短链”来跳转到自己app的特定页面.
event.URL = [NSURL URLWithString:urlStr];
注意: 系统日历中, 呈现给用户的是其decode一次后的url
. 你可以将自己的URL放在notes(不会被decode)
中.
Error Domain=EKErrorDomain Code=1 "尚未设定日历。" UserInfo={NSLocalizedDescription=尚未设定日历。}
非代码问题, 打开日历, 可以看到右上角“+”是灰色的
, 说明本身是不可添加日历事件的.
解决方法: 设置->账号—>iCloud->日历
, 切换下开关, 并重启日历, 看右上角"+"
是否可用.