一、簡(jiǎn)介
EventKit 允許你的app 訪問(wèn)已經(jīng)存在于日歷和提醒里面的事件吃环,同時(shí)也允許你的app創(chuàng)建一個(gè)提醒事件添加到日歷或者提醒中也颤。用戶可以編輯刪除日歷和提醒里面的事件。EventKit 還可以添加鬧鈴郁轻,和重復(fù)提醒的事件翅娶。
EKEvent創(chuàng)建的事件在日歷中顯示文留,EKReminder創(chuàng)建的時(shí)間在提醒事項(xiàng)中顯示
注意:EKEvent 和 EKReminder都繼承于EKCalendarItem, EKCalendarItem類是日歷事件和提醒的抽象超類竭沫,此類提供常用的屬性和方法來(lái)訪問(wèn)日歷項(xiàng)的屬性燥翅,例如設(shè)置日歷的功能,標(biāo)題和位置蜕提,以及支持附加注釋森书,顯示與會(huì)者,設(shè)置多個(gè)鬧鐘和指定重復(fù)規(guī)則贯溅。EKCalendarItem 的calendarItemIdentifier 是它唯一標(biāo)示,使用EKCalendarItem *item = [store calendarItemWithIdentifier:identifer];可以通過(guò)一個(gè)唯一標(biāo)示獲取一個(gè)EKCalendarItem對(duì)象
二躲查、配置權(quán)限
iOS 10 之后如果app 想要訪問(wèn)日歷和提醒事項(xiàng)它浅,我們必須在 我們的app 的Info.plist文件中添加NSRemindersUsageDescription和NSCalendarsUsageDescription的key否則app會(huì)閃退
// 獲取日歷權(quán)限
EKAuthorizationStatus ekStatus = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent]
// 申請(qǐng)日歷權(quán)限
[self.eventStore] requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
}];
// 獲取提醒事項(xiàng)權(quán)限
EKAuthorizationStatus ekStatus = [EKEventStore authorizationStatusForEntityType: EKEntityTypeReminder]
// 申請(qǐng)?zhí)嵝咽马?xiàng)權(quán)限
[self.eventStore] requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError * _Nullable error) {
}];
三、創(chuàng)建自定義日歷
/**
* 創(chuàng)建日歷
*
* @param entityType 日歷類型 EKEntityTypeEvent EKEntityTypeReminder
* @param title 日歷標(biāo)題
* @param completion 回調(diào)方法
*/
- (void)createCustomCalendarWithEntityType:(EKEntityType)entityType title:(NSString *)title completion:(CalendarCompletion)completion {
// 創(chuàng)建日歷
EKCalendar * customCalendar = [EKCalendar calendarForEntityType:entityType eventStore:self.eventStore];
// 必須設(shè)置source镣煮,否則無(wú)法創(chuàng)建calendar
customCalendar.source = [self getAvailableCalendarSource];
customCalendar.title = title;
NSError *error = nil;
BOOL isSuccess = [self.eventStore saveCalendar:customCalendar commit:YES error:&error];
if (!error) {
if (![NSString isBlankString:customCalendar.calendarIdentifier]) {
//存儲(chǔ)calendarIdentifier
NSString *calendarIdfLocalKey = nil;
if (entityType == EKEntityTypeEvent) {
calendarIdfLocalKey = kEventCalendarIdentifierLocalKey;
}else{
calendarIdfLocalKey = kReminderCalendarIdentifierLocalKey;
}
[XTUserDefault setValue:customCalendar.calendarIdentifier forKey:calendarIdfLocalKey];
}else{
isSuccess = NO;
error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"eventIdentifier不存在"}];
}
}else{
isSuccess = NO;
}
!completion?:completion(isSuccess,error);
}
- (EKSource *)getAvailableCalendarSource {
EKSource *localSource = nil;
for (EKSource *source in self.eventStore.sources){
if (source.sourceType == EKSourceTypeCalDAV && [source.title isEqualToString:@"iCloud"]){
localSource = source;
break;
}
}
if (localSource == nil){
for (EKSource *source in self.eventStore.sources){
if (source.sourceType == EKSourceTypeLocal){
localSource = source;
break;
}
}
}
if (localSource == nil) {
NSLog(@"XTCalendarEventManager getAvailableCalendarSource error");
}
return localSource;
}
注意1:創(chuàng)建的EKCalendar必須指定source姐霍,否則saveCalendar會(huì)失敗
注意2: 不是所有的source都可用于添加提醒事件的,一般來(lái)說(shuō)典唇,系統(tǒng)開(kāi)啟iCloud镊折,使用iCloud的Source,如果系統(tǒng)關(guān)閉iCloud介衔,使用本地Source
注意3:因?yàn)?EventStore 是 Calendar database 的數(shù)據(jù)庫(kù)引擎恨胚,所以應(yīng)該盡量少的對(duì)他進(jìn)行創(chuàng)建和銷毀,所以推薦使用EventStore的時(shí)候使用單例模式
注意4: 需要本地保存創(chuàng)建的Calendar的identifier炎咖。
四赃泡、創(chuàng)建日歷提醒事件EKEvent
/**
* 添加日歷提醒事項(xiàng)
*
* @param eventIdentifierLocalKey 事件ID 本地存儲(chǔ)Key
* @param title 事件標(biāo)題
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param allDay 是否全天
* @param alarmArray 鬧鐘集合(傳nil,則沒(méi)有)
* @param notes 事件備注(傳nil乘盼,則沒(méi)有)
* @param url 事件url(傳nil升熊,則沒(méi)有)
* @param completion 回調(diào)方法
*/
- (void)createCalendarEventWithEventIdentifierLocalKey:(NSString *)eventIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate endDate:(NSDate *)endDate allDay:(BOOL)allDay alarmArray:(NSArray <NSString *> * __nullable)alarmArray url:(NSURL * __nullable)url completion:(CalendarCompletion)completion {
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSError * authorityError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"未授權(quán)"}];
!completion?:completion(NO,authorityError);
return;
}
BOOL isSuccess = NO;
EKEvent *event = [EKEvent eventWithEventStore:self.eventStore];
event.title = title;
event.allDay = allDay;
event.notes = notes;
event.URL = url?:[NSURL URLWithString:@"xtcloudmeeting://"];
event.startDate = startDate;
event.endDate = endDate;
//添加鬧鐘提醒
if (alarmArray && alarmArray.count > 0) {
for (NSString *timeString in alarmArray) {
[event addAlarm:[EKAlarm alarmWithRelativeOffset:[timeString integerValue]]];
}
}
// 存儲(chǔ)到日歷源中
EKCalendar *eventCalendar = [self findCustomCalendar:EKEntityTypeEvent];
if (eventCalendar) {
[event setCalendar:eventCalendar];
}else{
[event setCalendar:[self.eventStore defaultCalendarForNewEvents]];
NSLog(@"XTCalendarEventManager save defaultCalendarForNewEvents");
}
// 保存日歷
NSError *isError;
isSuccess = [self.eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&isError];
if (!isError) {
if (![NSString isBlankString:event.eventIdentifier] && ![NSString isBlankString:eventIdentifierLocalKey]) {
//存儲(chǔ)日歷ID
[XTUserDefault setValue:event.eventIdentifier forKey:[self getCalendarItemLocalKey:eventIdentifierLocalKey type:EKEntityTypeEvent]];
}else{
isSuccess = NO;
isError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"eventIdentifier不存在"}];
}
}
!completion?:completion(isSuccess,isError);
NSLog(@"XTCalendarEventManager createCalendarEventWithEventIdentifierLocalKey %@",eventIdentifierLocalKey);
}
注意:也需要保存創(chuàng)建的EKEvent的identifier
五、查詢EKEvent
/**
* 查日歷事件
*
* @param eventIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (EKEvent *)checkCalendarEventWithIdentifier:(NSString *)eventIdentifierLocalKey{
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSLog(@"XTCalendarEventManager checkCalendarEventWithIdentifier 未授權(quán)");
return nil;
}
NSString *eIdentifier = [XTUserDefault getValueForKey:[self getCalendarItemLocalKey:eventIdentifierLocalKey type:EKEntityTypeEvent]];
if (![NSString isBlankString:eIdentifier]) {
EKEvent *event = [self.eventStore eventWithIdentifier:eIdentifier];
return event;
}
return nil;
}
/**
* 查日歷事件(可查詢一段時(shí)間內(nèi)的事件)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param modifytitle 標(biāo)題绸栅,為空則都要查詢
*/
- (NSArray *)checkCalendarEventWithStartDate:(NSDate *)startDate endDate:(NSDate *)endDate modifytitle:(NSString * __nullable)modifytitle {
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSLog(@"XTCalendarEventManager checkCalendarEventWithDate 未授權(quán)");
return nil;
}
// 查詢到所有的日歷
EKCalendar *eventCalendar = [self findCustomCalendar:EKEntityTypeEvent];
if (!eventCalendar) {
eventCalendar = [self.eventStore defaultCalendarForNewEvents];
}
NSPredicate *predicate = [self.eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:@[eventCalendar]];
// 獲取到范圍內(nèi)的所有事件
NSArray *request = [self.eventStore eventsMatchingPredicate:predicate];
// 按開(kāi)始事件進(jìn)行排序
request = [request sortedArrayUsingSelector:@selector(compareStartDateWithEvent:)];
if ([NSString isBlankString:modifytitle]) {
return request;
}else{
NSMutableArray *onlyRequest = [NSMutableArray array];
for (int i = 0; i < request.count; i++) {
EKEvent *event = request[i];
if (event.title && [event.title isEqualToString:modifytitle]) {
[onlyRequest addObject:event];
}
}
return onlyRequest;
}
}
六级野、刪除EKEvent
/**
* 刪除日歷事件(刪除單個(gè))
*
* @param eventIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (BOOL)deleteCalendarEventWithIdentifier:(NSString *)eventIdentifierLocalKey{
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSLog(@"XTCalendarEventManager deleteCalendarEventWithIdentifier 未授權(quán)");
return NO;
}
BOOL isDelete = NO;
NSString *eIdentifier = [XTUserDefault getValueForKey:[self getCalendarItemLocalKey:eventIdentifierLocalKey type:EKEntityTypeEvent]];
EKEvent *event;
if (![NSString isBlankString:eIdentifier]) {
event = [self.eventStore eventWithIdentifier:eIdentifier];
isDelete = [self.eventStore removeEvent:event span:EKSpanThisEvent error:nil];
}
NSLog(@"XTCalendarEventManager deleteCalendarEventWithIdentifier %@ %d",eventIdentifierLocalKey,isDelete);
return isDelete;
}
/**
* 刪除日歷事件(可刪除一段時(shí)間內(nèi)的事件)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param modifytitle 標(biāo)題,為空則都要?jiǎng)h除
*/
- (BOOL)deleteCalendarEventWithStartDate:(NSDate *)startDate endDate:(NSDate *)endDate modifytitle:(NSString * __nullable)modifytitle {
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSLog(@"XTCalendarEventManager deleteCalendarEventWithDate 未授權(quán)");
return NO;
}
// 獲取到此事件
NSArray *request = [self checkCalendarEventWithStartDate:startDate endDate:endDate modifytitle:modifytitle];
for (int i = 0; i < request.count; i ++) {
// 刪除這一條事件
EKEvent *event = request[i];
NSError*error =nil;
// commit:NO:最后再一次性提交
[self.eventStore removeEvent:event span:EKSpanThisEvent commit:NO error:&error];
}
//一次提交所有操作到事件庫(kù)
NSError *errored = nil;
BOOL commitSuccess= [self.eventStore commit:&errored];
return commitSuccess;
}
七粹胯、修改EKEvent
/**
* 修改日歷事件
*
* @param eventIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地key
* @param title 修改事件標(biāo)題
* @param startDate 修改開(kāi)始時(shí)間
* @param endDate 修改結(jié)束時(shí)間
* @param allDay 修改是否全天
* @param alarmArray 修改鬧鐘集合
* @param notes 修改事件備注
* @param url 修改事件url
* @param completion 回調(diào)方法
*/
- (void)modifyCalendarEventWithEventIdentifierLocalKey:(NSString *)eventIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate endDate:(NSDate *)endDate allDay:(BOOL)allDay alarmArray:(NSArray <NSString *> * __nullable)alarmArray url:(NSURL * __nullable)url completion:(CalendarCompletion)completion{
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSError * authorityError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"未授權(quán)"}];
!completion?:completion(NO,authorityError);
return;
}
// 獲取到此事件
EKEvent *event = [self checkCalendarEventWithIdentifier:eventIdentifierLocalKey];
if (event) {
BOOL isDelete = [self deleteCalendarEventWithIdentifier:eventIdentifierLocalKey];
NSLog(@"XTCalendarEventManager modify delete %d",isDelete);
[self createCalendarEventWithEventIdentifierLocalKey:eventIdentifierLocalKey calendarTitle:title notes:notes startDate:startDate endDate:endDate allDay:allDay alarmArray:alarmArray url:url completion:completion];
}else{
// 沒(méi)有此條日歷
[self createCalendarEventWithEventIdentifierLocalKey:eventIdentifierLocalKey calendarTitle:title notes:notes startDate:startDate endDate:endDate allDay:allDay alarmArray:alarmArray url:url completion:completion];
}
}
八蓖柔、創(chuàng)建EKReminder提醒事項(xiàng)
和EKEvent類似
/**
* 添加Reminder提醒事項(xiàng)
*
* @param reminderIdentifierLocalKey 事件ID 本地存儲(chǔ)Key
* @param title 事件標(biāo)題
* @param startDate 開(kāi)始時(shí)間
* @param dueDate 預(yù)計(jì)結(jié)束時(shí)間
* @param alarmDate 鬧鐘Date
* @param notes 事件備注(傳nil,則沒(méi)有)
* @param url 事件url(傳nil风纠,則沒(méi)有)
* @param completion 回調(diào)方法
*/
- (void)createCalendarReminderWithReminderIdentifierLocalKey:(NSString *)reminderIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate dueDate:(NSDate *)dueDate alarmDate:(NSDate *)alarmDate url:(NSURL * __nullable)url completion:(CalendarCompletion)completion {
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
NSError * authorityError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"未授權(quán)"}];
!completion?:completion(NO,authorityError);
return;
}
EKReminder *reminder = [EKReminder reminderWithEventStore:self.eventStore];
reminder.title = title;
reminder.notes = notes;
reminder.URL = url?:[NSURL URLWithString:@"xtcloudmeeting://"];
reminder.startDateComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:startDate];
reminder.dueDateComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:dueDate];
//添加鬧鐘提醒
[reminder addAlarm:[EKAlarm alarmWithAbsoluteDate:alarmDate]];
// 存儲(chǔ)到日歷源中
EKCalendar *reminderCalendar = [self findCustomCalendar:EKEntityTypeReminder];
if (reminderCalendar) {
[reminder setCalendar:reminderCalendar];
}else{
[reminder setCalendar:self.eventStore.defaultCalendarForNewReminders];
}
NSError *error = nil;
BOOL isSuccess = [self.eventStore saveReminder:reminder commit:YES error:&error];
if (!error) {
if (![NSString isBlankString:reminder.calendarItemIdentifier] && ![NSString isBlankString:reminderIdentifierLocalKey]) {
[XTUserDefault setValue:reminder.calendarItemIdentifier forKey:[self getCalendarItemLocalKey:reminderIdentifierLocalKey type:EKEntityTypeReminder]];
}else{
isSuccess = NO;
error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"eventIdentifier不存在"}];
}
}else{
isSuccess = NO;
}
!completion?:completion(isSuccess,error);
NSLog(@"XTCalendarEventManager createCalendarReminderWithReminderIdentifierLocalKey %@",reminderIdentifierLocalKey);
}
注意:
- EKReminder 可添加多個(gè)鬧鐘Alarm,但實(shí)際測(cè)試中發(fā)現(xiàn)渊抽,只有第一個(gè)會(huì)生效
- Alarm 通過(guò)alarmWithRelativeOffset 創(chuàng)建時(shí),后面參數(shù)offset 表示鬧鐘出發(fā)時(shí)間和參照時(shí)間點(diǎn)的偏移量议忽,為負(fù)數(shù)時(shí)懒闷,表示在參照時(shí)間點(diǎn)前offset秒觸發(fā)。此時(shí)如果把Alarm添加到EKEvent上,參照時(shí)間點(diǎn)為startDate愤估,如果是添加到EKReminder上帮辟,參照時(shí)間點(diǎn)為dueDate。建議給EKReminder添加鬧鐘Alarm時(shí)玩焰,使用alarmWithAbsoluteDate方式創(chuàng)建Alarm
九由驹、查詢EKReminder
/**
* 查Reminder提醒項(xiàng)
*
* @param reminderIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (EKReminder *)checkCalendarReminderWithIdentifier:(NSString *)reminderIdentifierLocalKey{
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
NSLog(@"XTCalendarEventManager checkCalendarReminderWithIdentifier 未授權(quán)");
return nil;
}
NSString *eIdentifier = [XTUserDefault getValueForKey:[self getCalendarItemLocalKey:reminderIdentifierLocalKey type:EKEntityTypeReminder]];
if (![NSString isBlankString:eIdentifier]) {
EKCalendarItem *calendarItem = [self.eventStore calendarItemWithIdentifier:eIdentifier];
if ([calendarItem isKindOfClass:[EKReminder class]]) {
return (EKReminder *)calendarItem;
}
return nil;
}
return nil;
}
/**
* 查詢Reminder提醒事項(xiàng) (一段時(shí)間)(以dueDate為參照)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param completion 回調(diào)方法
*/
- (void)checkCalendarIncompleteRemindersWithDueDateStarting:(nullable NSDate *)startDate endDate:(nullable NSDate *)endDate completion:(CalendarFetchDataCompletion)completion{
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
!completion?:completion(nil);
return;
}
EKCalendar *reminderCalendar = [self findCustomCalendar:EKEntityTypeReminder];
if (!reminderCalendar) {
reminderCalendar = [self.eventStore defaultCalendarForNewReminders];
}
NSPredicate *predicate = [self.eventStore predicateForIncompleteRemindersWithDueDateStarting:startDate ending:endDate calendars:@[reminderCalendar]];
[self.eventStore fetchRemindersMatchingPredicate:predicate completion:^(NSArray<EKReminder *> * _Nullable reminders) {
!completion?:completion(reminders);
}];
}
十、刪除EKReminder
/**
* 刪除Reminber(刪除單個(gè))
*
* @param reminderIdentifierLocalKey reminder ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (BOOL)deleteCalendarReminderWithIdentifier:(NSString *)reminderIdentifierLocalKey {
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
NSLog(@"XTCalendarEventManager deleteCalendarReminderWithIdentifier 未授權(quán)");
return NO;
}
BOOL isDelete = NO;
EKReminder *reminder = [self checkCalendarReminderWithIdentifier:reminderIdentifierLocalKey];
if (reminder) {
isDelete = [self.eventStore removeReminder:reminder commit:YES error:nil];
}
NSLog(@"XTCalendarEventManager deleteCalendarReminderWithIdentifier %@ %d",reminderIdentifierLocalKey,isDelete);
return isDelete;
}
/**
* 刪除Reminder提醒事項(xiàng) (一段時(shí)間)(以dueDate為參照)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param completion 回調(diào)方法
*/
- (void)deleteCalendarIncompleteRemindersWithDueDateStarting:(nullable NSDate *)startDate endDate:(nullable NSDate *)endDate completion:(CalendarCompletion)completion{
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
NSError * authorityError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"未授權(quán)"}];
!completion?:completion(NO,authorityError);
return;
}
weakify_self
[self checkCalendarIncompleteRemindersWithDueDateStarting:startDate endDate:endDate completion:^(NSArray *itemArray) {
strongify_self
for (int i=0; i<itemArray.count; i++) {
EKReminder *tempReminder = (EKReminder *)[itemArray objectAtIndex:i];
[self.eventStore removeReminder:tempReminder commit:NO error:nil];
}
NSError *error = nil;
BOOL commitSucces = [self.eventStore commit:&error];
!completion?:completion(commitSucces,error);
}];
}
十一昔园、 修改EKReminder
/**
* 修改Reminder提醒事項(xiàng)
*
* @param reminderIdentifierLocalKey 事件ID 本地存儲(chǔ)Key
* @param title 事件標(biāo)題
* @param startDate 開(kāi)始時(shí)間
* @param dueDate 預(yù)計(jì)結(jié)束時(shí)間
* @param alarmDate 鬧鐘Date
* @param notes 事件備注(傳nil蔓榄,則沒(méi)有)
* @param url 事件url(傳nil,則沒(méi)有)
* @param completion 回調(diào)方法
*/
- (void)modifyCalendarReminderWithReminderIdentifierLocalKey:(NSString *)reminderIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate dueDate:(NSDate *)dueDate alarmDate:(NSDate *)alarmDate url:(NSURL * __nullable)url completion:(CalendarCompletion)completion {
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
NSError * authorityError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"未授權(quán)"}];
!completion?:completion(NO,authorityError);
return;
}
EKReminder *tempReminder = [self checkCalendarReminderWithIdentifier:reminderIdentifierLocalKey];
if (tempReminder) {
[self deleteCalendarReminderWithIdentifier:reminderIdentifierLocalKey];
[self createCalendarReminderWithReminderIdentifierLocalKey:reminderIdentifierLocalKey calendarTitle:title notes:notes startDate:startDate dueDate:dueDate alarmDate:alarmDate url:url completion:completion];
}else{
[self createCalendarReminderWithReminderIdentifierLocalKey:reminderIdentifierLocalKey calendarTitle:title notes:notes startDate:startDate dueDate:dueDate alarmDate:alarmDate url:url completion:completion];
}
}
完整代碼
XTCalendarEventManager.h
#import <Foundation/Foundation.h>
#import <EventKit/EventKit.h>
typedef void(^__nullable CalendarCompletion)(BOOL isSuccess, NSError * _Nullable error);
typedef void(^__nullable CalendarFetchDataCompletion)(NSArray * _Nullable itemArray);
NS_ASSUME_NONNULL_BEGIN
@interface XTCalendarEventManager : NSObject
AS_SINGLETON(XTCalendarEventManager);
#pragma mark - 日歷提醒 -
/**
* 添加日歷提醒事項(xiàng)
*
* @param eventIdentifierLocalKey 事件ID 本地存儲(chǔ)Key
* @param title 事件標(biāo)題
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param allDay 是否全天
* @param alarmArray 鬧鐘集合(傳nil默刚,則沒(méi)有)
* @param notes 事件備注(傳nil甥郑,則沒(méi)有)
* @param url 事件url(傳nil,則沒(méi)有)
* @param completion 回調(diào)方法
*/
- (void)createCalendarEventWithEventIdentifierLocalKey:(NSString *)eventIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate endDate:(NSDate *)endDate allDay:(BOOL)allDay alarmArray:(NSArray <NSString *> * __nullable)alarmArray url:(NSURL * __nullable)url completion:(CalendarCompletion)completion;
/**
* 查日歷事件
*
* @param eventIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (EKEvent *)checkCalendarEventWithIdentifier:(NSString *)eventIdentifierLocalKey;
/**
* 查日歷事件(可查詢一段時(shí)間內(nèi)的事件)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param modifytitle 標(biāo)題荤西,為空則都要查詢
*/
- (NSArray *)checkCalendarEventWithStartDate:(NSDate *)startDate endDate:(NSDate *)endDate modifytitle:(NSString * __nullable)modifytitle;
/**
* 刪除日歷事件(刪除單個(gè))
*
* @param eventIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (BOOL)deleteCalendarEventWithIdentifier:(NSString *)eventIdentifierLocalKey;
/**
* 刪除日歷事件(可刪除一段時(shí)間內(nèi)的事件)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param modifytitle 標(biāo)題澜搅,為空則都要?jiǎng)h除
*/
- (BOOL)deleteCalendarEventWithStartDate:(NSDate *)startDate endDate:(NSDate *)endDate modifytitle:(NSString * __nullable)modifytitle;
/**
* 修改日歷事件
*
* @param eventIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地key
* @param title 修改事件標(biāo)題
* @param startDate 修改開(kāi)始時(shí)間
* @param endDate 修改結(jié)束時(shí)間
* @param allDay 修改是否全天
* @param alarmArray 修改鬧鐘集合
* @param notes 修改事件備注
* @param url 修改事件url
* @param completion 回調(diào)方法
*/
- (void)modifyCalendarEventWithEventIdentifierLocalKey:(NSString *)eventIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate endDate:(NSDate *)endDate allDay:(BOOL)allDay alarmArray:(NSArray <NSString *> * __nullable)alarmArray url:(NSURL * __nullable)url completion:(CalendarCompletion)completion;
#pragma mark - Reminder 提醒 -
/**
* 添加Reminder提醒事項(xiàng)
*
* @param reminderIdentifierLocalKey 事件ID 本地存儲(chǔ)Key
* @param title 事件標(biāo)題
* @param startDate 開(kāi)始時(shí)間
* @param dueDate 預(yù)計(jì)結(jié)束時(shí)間
* @param alarmDate 鬧鐘Date
* @param notes 事件備注(傳nil,則沒(méi)有)
* @param url 事件url(傳nil邪锌,則沒(méi)有)
* @param completion 回調(diào)方法
*/
- (void)createCalendarReminderWithReminderIdentifierLocalKey:(NSString *)reminderIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate dueDate:(NSDate *)dueDate alarmDate:(NSDate *)alarmDate url:(NSURL * __nullable)url completion:(CalendarCompletion)completion;
/**
* 查Reminder提醒項(xiàng)
*
* @param reminderIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (EKReminder *)checkCalendarReminderWithIdentifier:(NSString *)reminderIdentifierLocalKey;
/**
* 查詢Reminder提醒事項(xiàng) (一段時(shí)間)(以dueDate為參照)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param completion 回調(diào)方法
*/
- (void)checkCalendarIncompleteRemindersWithDueDateStarting:(nullable NSDate *)startDate endDate:(nullable NSDate *)endDate completion:(CalendarFetchDataCompletion)completion;
/**
* 刪除Reminber(刪除單個(gè))
*
* @param reminderIdentifierLocalKey reminder ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (BOOL)deleteCalendarReminderWithIdentifier:(NSString *)reminderIdentifierLocalKey;
/**
* 刪除Reminder提醒事項(xiàng) (一段時(shí)間)(以dueDate為參照)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param completion 回調(diào)方法
*/
- (void)deleteCalendarIncompleteRemindersWithDueDateStarting:(nullable NSDate *)startDate endDate:(nullable NSDate *)endDate completion:(CalendarCompletion)completion;
/**
* 修改Reminder提醒事項(xiàng)
*
* @param reminderIdentifierLocalKey 事件ID 本地存儲(chǔ)Key
* @param title 事件標(biāo)題
* @param startDate 開(kāi)始時(shí)間
* @param dueDate 預(yù)計(jì)結(jié)束時(shí)間
* @param alarmDate 鬧鐘Date
* @param notes 事件備注(傳nil勉躺,則沒(méi)有)
* @param url 事件url(傳nil,則沒(méi)有)
* @param completion 回調(diào)方法
*/
- (void)modifyCalendarReminderWithReminderIdentifierLocalKey:(NSString *)reminderIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate dueDate:(NSDate *)dueDate alarmDate:(NSDate *)alarmDate url:(NSURL * __nullable)url completion:(CalendarCompletion)completion;
@end
NS_ASSUME_NONNULL_END
XTCalendarEventManager.m
#import "XTCalendarEventManager.h"
#import "NSString+isBlank.h"
#import "XTAuthorityManager.h"
static NSString *const kEventCalendarIdentifierLocalKey = @"XT_CloudMeeting_EventCalendar_Identifier_Key";
static NSString *const kReminderCalendarIdentifierLocalKey = @"XT_CloudMeeting_ReminderCalendar_Identifier_Key";
static NSString *const kEventIdentifier = @"XT_Calendar_Event_Key";
static NSString *const kReminderIIdentifier = @"XT_Calendar_Reminder_Key";
@interface XTCalendarEventManager ()
@property (nonatomic,strong) EKEventStore *eventStore;
@property (nonatomic,strong) NSMutableArray <NSString *> *calendarItemIdentifierArray; // 存儲(chǔ)日歷唯一標(biāo)識(shí)符
@end
@implementation XTCalendarEventManager
DEF_SINGLETON(XTCalendarEventManager);
- (instancetype)init {
self = [super init];
if (self) {
self.eventStore = [[EKEventStore alloc] init];
self.calendarItemIdentifierArray = [[NSMutableArray alloc] init];
[self crateCalendar];
}
return self;
}
- (void)crateCalendar {
EKCalendar *eventCalendar = [self findCustomCalendar:EKEntityTypeEvent];
if (!eventCalendar) {
[self createCustomCalendarWithEntityType:EKEntityTypeEvent title:@"云會(huì)議" completion:nil];
}
EKCalendar *reminderCalendar = [self findCustomCalendar:EKEntityTypeReminder];
if (!reminderCalendar) {
[self createCustomCalendarWithEntityType:EKEntityTypeReminder title:@"云會(huì)議" completion:nil];
}
}
/**
* 創(chuàng)建日歷
*
* @param entityType 日歷類型 EKEntityTypeEvent EKEntityTypeReminder
* @param title 日歷標(biāo)題
* @param completion 回調(diào)方法
*/
- (void)createCustomCalendarWithEntityType:(EKEntityType)entityType title:(NSString *)title completion:(CalendarCompletion)completion {
// 創(chuàng)建日歷
EKCalendar * customCalendar = [EKCalendar calendarForEntityType:entityType eventStore:self.eventStore];
// 必須設(shè)置source觅丰,否則無(wú)法創(chuàng)建calendar
customCalendar.source = [self getAvailableCalendarSource];
customCalendar.title = title;
NSError *error = nil;
BOOL isSuccess = [self.eventStore saveCalendar:customCalendar commit:YES error:&error];
if (!error) {
if (![NSString isBlankString:customCalendar.calendarIdentifier]) {
//存儲(chǔ)calendarIdentifier
NSString *calendarIdfLocalKey = nil;
if (entityType == EKEntityTypeEvent) {
calendarIdfLocalKey = kEventCalendarIdentifierLocalKey;
}else{
calendarIdfLocalKey = kReminderCalendarIdentifierLocalKey;
}
[XTUserDefault setValue:customCalendar.calendarIdentifier forKey:calendarIdfLocalKey];
}else{
isSuccess = NO;
error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"eventIdentifier不存在"}];
}
}else{
isSuccess = NO;
}
!completion?:completion(isSuccess,error);
}
#pragma mark - 日歷提醒 -
/**
* 添加日歷提醒事項(xiàng)
*
* @param eventIdentifierLocalKey 事件ID 本地存儲(chǔ)Key
* @param title 事件標(biāo)題
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param allDay 是否全天
* @param alarmArray 鬧鐘集合(傳nil饵溅,則沒(méi)有)
* @param notes 事件備注(傳nil,則沒(méi)有)
* @param url 事件url(傳nil妇萄,則沒(méi)有)
* @param completion 回調(diào)方法
*/
- (void)createCalendarEventWithEventIdentifierLocalKey:(NSString *)eventIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate endDate:(NSDate *)endDate allDay:(BOOL)allDay alarmArray:(NSArray <NSString *> * __nullable)alarmArray url:(NSURL * __nullable)url completion:(CalendarCompletion)completion {
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSError * authorityError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"未授權(quán)"}];
!completion?:completion(NO,authorityError);
return;
}
BOOL isSuccess = NO;
EKEvent *event = [EKEvent eventWithEventStore:self.eventStore];
event.title = title;
event.allDay = allDay;
event.notes = notes;
event.URL = url?:[NSURL URLWithString:@"xtcloudmeeting://"];
event.startDate = startDate;
event.endDate = endDate;
//添加鬧鐘提醒
if (alarmArray && alarmArray.count > 0) {
for (NSString *timeString in alarmArray) {
[event addAlarm:[EKAlarm alarmWithRelativeOffset:[timeString integerValue]]];
}
}
// 存儲(chǔ)到日歷源中
EKCalendar *eventCalendar = [self findCustomCalendar:EKEntityTypeEvent];
if (eventCalendar) {
[event setCalendar:eventCalendar];
}else{
[event setCalendar:[self.eventStore defaultCalendarForNewEvents]];
NSLog(@"XTCalendarEventManager save defaultCalendarForNewEvents");
}
// 保存日歷
NSError *isError;
isSuccess = [self.eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&isError];
if (!isError) {
if (![NSString isBlankString:event.eventIdentifier] && ![NSString isBlankString:eventIdentifierLocalKey]) {
//存儲(chǔ)日歷ID
[XTUserDefault setValue:event.eventIdentifier forKey:[self getCalendarItemLocalKey:eventIdentifierLocalKey type:EKEntityTypeEvent]];
}else{
isSuccess = NO;
isError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"eventIdentifier不存在"}];
}
}
!completion?:completion(isSuccess,isError);
NSLog(@"XTCalendarEventManager createCalendarEventWithEventIdentifierLocalKey %@",eventIdentifierLocalKey);
}
/**
* 查日歷事件
*
* @param eventIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (EKEvent *)checkCalendarEventWithIdentifier:(NSString *)eventIdentifierLocalKey{
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSLog(@"XTCalendarEventManager checkCalendarEventWithIdentifier 未授權(quán)");
return nil;
}
NSString *eIdentifier = [XTUserDefault getValueForKey:[self getCalendarItemLocalKey:eventIdentifierLocalKey type:EKEntityTypeEvent]];
if (![NSString isBlankString:eIdentifier]) {
EKEvent *event = [self.eventStore eventWithIdentifier:eIdentifier];
return event;
}
return nil;
}
/**
* 查日歷事件(可查詢一段時(shí)間內(nèi)的事件)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param modifytitle 標(biāo)題概说,為空則都要查詢
*/
- (NSArray *)checkCalendarEventWithStartDate:(NSDate *)startDate endDate:(NSDate *)endDate modifytitle:(NSString * __nullable)modifytitle {
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSLog(@"XTCalendarEventManager checkCalendarEventWithDate 未授權(quán)");
return nil;
}
// 查詢到所有的日歷
EKCalendar *eventCalendar = [self findCustomCalendar:EKEntityTypeEvent];
if (!eventCalendar) {
eventCalendar = [self.eventStore defaultCalendarForNewEvents];
}
NSPredicate *predicate = [self.eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:@[eventCalendar]];
// 獲取到范圍內(nèi)的所有事件
NSArray *request = [self.eventStore eventsMatchingPredicate:predicate];
// 按開(kāi)始事件進(jìn)行排序
request = [request sortedArrayUsingSelector:@selector(compareStartDateWithEvent:)];
if ([NSString isBlankString:modifytitle]) {
return request;
}else{
NSMutableArray *onlyRequest = [NSMutableArray array];
for (int i = 0; i < request.count; i++) {
EKEvent *event = request[i];
if (event.title && [event.title isEqualToString:modifytitle]) {
[onlyRequest addObject:event];
}
}
return onlyRequest;
}
}
/**
* 刪除日歷事件(刪除單個(gè))
*
* @param eventIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (BOOL)deleteCalendarEventWithIdentifier:(NSString *)eventIdentifierLocalKey{
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSLog(@"XTCalendarEventManager deleteCalendarEventWithIdentifier 未授權(quán)");
return NO;
}
BOOL isDelete = NO;
NSString *eIdentifier = [XTUserDefault getValueForKey:[self getCalendarItemLocalKey:eventIdentifierLocalKey type:EKEntityTypeEvent]];
EKEvent *event;
if (![NSString isBlankString:eIdentifier]) {
event = [self.eventStore eventWithIdentifier:eIdentifier];
isDelete = [self.eventStore removeEvent:event span:EKSpanThisEvent error:nil];
}
NSLog(@"XTCalendarEventManager deleteCalendarEventWithIdentifier %@ %d",eventIdentifierLocalKey,isDelete);
return isDelete;
}
/**
* 刪除日歷事件(可刪除一段時(shí)間內(nèi)的事件)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param modifytitle 標(biāo)題,為空則都要?jiǎng)h除
*/
- (BOOL)deleteCalendarEventWithStartDate:(NSDate *)startDate endDate:(NSDate *)endDate modifytitle:(NSString * __nullable)modifytitle {
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSLog(@"XTCalendarEventManager deleteCalendarEventWithDate 未授權(quán)");
return NO;
}
// 獲取到此事件
NSArray *request = [self checkCalendarEventWithStartDate:startDate endDate:endDate modifytitle:modifytitle];
for (int i = 0; i < request.count; i ++) {
// 刪除這一條事件
EKEvent *event = request[i];
NSError*error =nil;
// commit:NO:最后再一次性提交
[self.eventStore removeEvent:event span:EKSpanThisEvent commit:NO error:&error];
}
//一次提交所有操作到事件庫(kù)
NSError *errored = nil;
BOOL commitSuccess= [self.eventStore commit:&errored];
return commitSuccess;
}
/**
* 修改日歷事件
*
* @param eventIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地key
* @param title 修改事件標(biāo)題
* @param startDate 修改開(kāi)始時(shí)間
* @param endDate 修改結(jié)束時(shí)間
* @param allDay 修改是否全天
* @param alarmArray 修改鬧鐘集合
* @param notes 修改事件備注
* @param url 修改事件url
* @param completion 回調(diào)方法
*/
- (void)modifyCalendarEventWithEventIdentifierLocalKey:(NSString *)eventIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate endDate:(NSDate *)endDate allDay:(BOOL)allDay alarmArray:(NSArray <NSString *> * __nullable)alarmArray url:(NSURL * __nullable)url completion:(CalendarCompletion)completion{
if (![self checkCaledarAuthority:EKEntityTypeEvent]) {
NSError * authorityError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"未授權(quán)"}];
!completion?:completion(NO,authorityError);
return;
}
// 獲取到此事件
EKEvent *event = [self checkCalendarEventWithIdentifier:eventIdentifierLocalKey];
if (event) {
BOOL isDelete = [self deleteCalendarEventWithIdentifier:eventIdentifierLocalKey];
NSLog(@"XTCalendarEventManager modify delete %d",isDelete);
[self createCalendarEventWithEventIdentifierLocalKey:eventIdentifierLocalKey calendarTitle:title notes:notes startDate:startDate endDate:endDate allDay:allDay alarmArray:alarmArray url:url completion:completion];
}else{
// 沒(méi)有此條日歷
[self createCalendarEventWithEventIdentifierLocalKey:eventIdentifierLocalKey calendarTitle:title notes:notes startDate:startDate endDate:endDate allDay:allDay alarmArray:alarmArray url:url completion:completion];
}
}
#pragma mark - Reminder 提醒 -
/**
* 添加Reminder提醒事項(xiàng)
*
* @param reminderIdentifierLocalKey 事件ID 本地存儲(chǔ)Key
* @param title 事件標(biāo)題
* @param startDate 開(kāi)始時(shí)間
* @param dueDate 預(yù)計(jì)結(jié)束時(shí)間
* @param alarmDate 鬧鐘Date
* @param notes 事件備注(傳nil嚣伐,則沒(méi)有)
* @param url 事件url(傳nil糖赔,則沒(méi)有)
* @param completion 回調(diào)方法
*/
- (void)createCalendarReminderWithReminderIdentifierLocalKey:(NSString *)reminderIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate dueDate:(NSDate *)dueDate alarmDate:(NSDate *)alarmDate url:(NSURL * __nullable)url completion:(CalendarCompletion)completion {
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
NSError * authorityError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"未授權(quán)"}];
!completion?:completion(NO,authorityError);
return;
}
EKReminder *reminder = [EKReminder reminderWithEventStore:self.eventStore];
reminder.title = title;
reminder.notes = notes;
reminder.URL = url?:[NSURL URLWithString:@"xtcloudmeeting://"];
reminder.startDateComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:startDate];
reminder.dueDateComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond fromDate:dueDate];
//添加鬧鐘提醒
[reminder addAlarm:[EKAlarm alarmWithAbsoluteDate:alarmDate]];
// 存儲(chǔ)到日歷源中
EKCalendar *reminderCalendar = [self findCustomCalendar:EKEntityTypeReminder];
if (reminderCalendar) {
[reminder setCalendar:reminderCalendar];
}else{
[reminder setCalendar:self.eventStore.defaultCalendarForNewReminders];
}
NSError *error = nil;
BOOL isSuccess = [self.eventStore saveReminder:reminder commit:YES error:&error];
if (!error) {
if (![NSString isBlankString:reminder.calendarItemIdentifier] && ![NSString isBlankString:reminderIdentifierLocalKey]) {
[XTUserDefault setValue:reminder.calendarItemIdentifier forKey:[self getCalendarItemLocalKey:reminderIdentifierLocalKey type:EKEntityTypeReminder]];
}else{
isSuccess = NO;
error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"eventIdentifier不存在"}];
}
}else{
isSuccess = NO;
}
!completion?:completion(isSuccess,error);
NSLog(@"XTCalendarEventManager createCalendarReminderWithReminderIdentifierLocalKey %@",reminderIdentifierLocalKey);
}
/**
* 查Reminder提醒項(xiàng)
*
* @param reminderIdentifierLocalKey 事件ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (EKReminder *)checkCalendarReminderWithIdentifier:(NSString *)reminderIdentifierLocalKey{
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
NSLog(@"XTCalendarEventManager checkCalendarReminderWithIdentifier 未授權(quán)");
return nil;
}
NSString *eIdentifier = [XTUserDefault getValueForKey:[self getCalendarItemLocalKey:reminderIdentifierLocalKey type:EKEntityTypeReminder]];
if (![NSString isBlankString:eIdentifier]) {
EKCalendarItem *calendarItem = [self.eventStore calendarItemWithIdentifier:eIdentifier];
if ([calendarItem isKindOfClass:[EKReminder class]]) {
return (EKReminder *)calendarItem;
}
return nil;
}
return nil;
}
/**
* 查詢Reminder提醒事項(xiàng) (一段時(shí)間)(以dueDate為參照)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param completion 回調(diào)方法
*/
- (void)checkCalendarIncompleteRemindersWithDueDateStarting:(nullable NSDate *)startDate endDate:(nullable NSDate *)endDate completion:(CalendarFetchDataCompletion)completion{
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
!completion?:completion(nil);
return;
}
EKCalendar *reminderCalendar = [self findCustomCalendar:EKEntityTypeReminder];
if (!reminderCalendar) {
reminderCalendar = [self.eventStore defaultCalendarForNewReminders];
}
NSPredicate *predicate = [self.eventStore predicateForIncompleteRemindersWithDueDateStarting:startDate ending:endDate calendars:@[reminderCalendar]];
[self.eventStore fetchRemindersMatchingPredicate:predicate completion:^(NSArray<EKReminder *> * _Nullable reminders) {
!completion?:completion(reminders);
}];
}
/**
* 刪除Reminber(刪除單個(gè))
*
* @param reminderIdentifierLocalKey reminder ID(標(biāo)識(shí)符) 本地存儲(chǔ)Key
*/
- (BOOL)deleteCalendarReminderWithIdentifier:(NSString *)reminderIdentifierLocalKey {
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
NSLog(@"XTCalendarEventManager deleteCalendarReminderWithIdentifier 未授權(quán)");
return NO;
}
BOOL isDelete = NO;
EKReminder *reminder = [self checkCalendarReminderWithIdentifier:reminderIdentifierLocalKey];
if (reminder) {
isDelete = [self.eventStore removeReminder:reminder commit:YES error:nil];
}
NSLog(@"XTCalendarEventManager deleteCalendarReminderWithIdentifier %@ %d",reminderIdentifierLocalKey,isDelete);
return isDelete;
}
/**
* 刪除Reminder提醒事項(xiàng) (一段時(shí)間)(以dueDate為參照)
*
* @param startDate 開(kāi)始時(shí)間
* @param endDate 結(jié)束時(shí)間
* @param completion 回調(diào)方法
*/
- (void)deleteCalendarIncompleteRemindersWithDueDateStarting:(nullable NSDate *)startDate endDate:(nullable NSDate *)endDate completion:(CalendarCompletion)completion{
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
NSError * authorityError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"未授權(quán)"}];
!completion?:completion(NO,authorityError);
return;
}
weakify_self
[self checkCalendarIncompleteRemindersWithDueDateStarting:startDate endDate:endDate completion:^(NSArray *itemArray) {
strongify_self
for (int i=0; i<itemArray.count; i++) {
EKReminder *tempReminder = (EKReminder *)[itemArray objectAtIndex:i];
[self.eventStore removeReminder:tempReminder commit:NO error:nil];
}
NSError *error = nil;
BOOL commitSucces = [self.eventStore commit:&error];
!completion?:completion(commitSucces,error);
}];
}
/**
* 修改Reminder提醒事項(xiàng)
*
* @param reminderIdentifierLocalKey 事件ID 本地存儲(chǔ)Key
* @param title 事件標(biāo)題
* @param startDate 開(kāi)始時(shí)間
* @param dueDate 預(yù)計(jì)結(jié)束時(shí)間
* @param alarmDate 鬧鐘Date
* @param notes 事件備注(傳nil拍棕,則沒(méi)有)
* @param url 事件url(傳nil穗慕,則沒(méi)有)
* @param completion 回調(diào)方法
*/
- (void)modifyCalendarReminderWithReminderIdentifierLocalKey:(NSString *)reminderIdentifierLocalKey calendarTitle:(NSString *)title notes:(NSString * __nullable)notes startDate:(NSDate *)startDate dueDate:(NSDate *)dueDate alarmDate:(NSDate *)alarmDate url:(NSURL * __nullable)url completion:(CalendarCompletion)completion {
if (![self checkCaledarAuthority:EKEntityTypeReminder]) {
NSError * authorityError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileWriteUnknownError userInfo:@{NSLocalizedDescriptionKey : @"未授權(quán)"}];
!completion?:completion(NO,authorityError);
return;
}
EKReminder *tempReminder = [self checkCalendarReminderWithIdentifier:reminderIdentifierLocalKey];
if (tempReminder) {
[self deleteCalendarReminderWithIdentifier:reminderIdentifierLocalKey];
[self createCalendarReminderWithReminderIdentifierLocalKey:reminderIdentifierLocalKey calendarTitle:title notes:notes startDate:startDate dueDate:dueDate alarmDate:alarmDate url:url completion:completion];
}else{
[self createCalendarReminderWithReminderIdentifierLocalKey:reminderIdentifierLocalKey calendarTitle:title notes:notes startDate:startDate dueDate:dueDate alarmDate:alarmDate url:url completion:completion];
}
}
#pragma mark - Pravite -
- (EKSource *)getAvailableCalendarSource {
EKSource *localSource = nil;
for (EKSource *source in self.eventStore.sources){
if (source.sourceType == EKSourceTypeCalDAV && [source.title isEqualToString:@"iCloud"]){
localSource = source;
break;
}
}
if (localSource == nil){
for (EKSource *source in self.eventStore.sources){
if (source.sourceType == EKSourceTypeLocal){
localSource = source;
break;
}
}
}
if (localSource == nil) {
NSLog(@"XTCalendarEventManager getAvailableCalendarSource error");
}
return localSource;
}
- (EKCalendar *)findCustomCalendar:(EKEntityType)entityType {
EKCalendar *customCalendar = nil;
NSString *calendarIdentifer = nil;
if (entityType == EKEntityTypeEvent) {
calendarIdentifer = [XTUserDefault getValueForKey:kEventCalendarIdentifierLocalKey];
}else{
calendarIdentifer = [XTUserDefault getValueForKey:kReminderCalendarIdentifierLocalKey];
}
if (![NSString isBlankString:calendarIdentifer]) {
NSArray *tempCalendarArray = [self.eventStore calendarsForEntityType:entityType];
for (int i = 0 ; i < tempCalendarArray.count; i ++) {
EKCalendar *temCalendar = tempCalendarArray[i];
if ([temCalendar.calendarIdentifier isEqualToString:calendarIdentifer]) {
customCalendar = temCalendar;
break;
}
}
}
return customCalendar;
}
- (NSString *)getCalendarItemLocalKey:(NSString *)identifierString type:(EKEntityType)type {
NSString *localKey = nil;
if (type == EKEntityTypeEvent) {
localKey = [NSString stringWithFormat:@"%@_%@",kEventIdentifier,identifierString];
}else{
localKey = [NSString stringWithFormat:@"%@_%@",kReminderIIdentifier,identifierString];
}
return localKey;
}
- (BOOL)checkCaledarAuthority:(EKEntityType)type {
BOOL isAuthority = NO;
XTAuthorityStatus status = XTAuthorityStatusNotDetermined;
if (type == EKEntityTypeEvent) {
status = [[XTAuthorityManager sharedInstance] checkCalendarAuthority];
}else {
status = [[XTAuthorityManager sharedInstance] checkReminderAuthority];
}
if (status == XTAuthorityStatusAuthorized) {
isAuthority = YES;
}
return isAuthority;
}
@end