1、Info.plist 中添加獲取系統(tǒng)日歷權(quán)限提醒
Privacy - Calendars Usage Description / 有助于您更好的管理日程

2、獲取權(quán)限
/**
EKAuthorizationStatusNotDetermined = 0,// 未進行授權(quán)選擇
EKAuthorizationStatusRestricted,//未授權(quán),且用戶無法更新,如家長控制情況下
EKAuthorizationStatusDenied, // 用戶拒絕App使用
EKAuthorizationStatusAuthorized, // 已授權(quán),可使用
*/
-(BOOL)getLocalCalendarAuthorization{
_eventStore = [[EKEventStore alloc]init];
EKAuthorizationStatus eventStatus = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
__block BOOL allow = NO;
if(eventStatus ==EKAuthorizationStatusNotDetermined){
//用戶尚未授權(quán),提示用戶授權(quán)。下邊的requestAccessToEntityType:方法可以調(diào)出系統(tǒng)授權(quán)彈窗
[_eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
//允許
allow = YES;
}else{
//不允許
allow = NO;
}
}];
}else if(eventStatus ==EKAuthorizationStatusAuthorized){
//用戶已經(jīng)允許授權(quán)。作相應(yīng)處理,比如查詢?nèi)諝v里今天的所有事件..
allow = YES;
}
return allow;
}
3、獲取所有的系統(tǒng)本地日歷
/// 獲取系統(tǒng)本地日歷事件
- (NSArray *)getLocalSystemCalendarEventWithStartDate:(NSDate *)startDate endDate:(NSDate *)endDate {
NSArray * eventArray = [_eventStore calendarsForEntityType:EKEntityTypeEvent];
NSMutableArray * onlyArray = [NSMutableArray array];
for (int i=0; i<eventArray.count; i++) {
EKCalendar * tempCalendar = eventArray[i];
EKCalendarType type = tempCalendar.type;
if (type == EKCalendarTypeCalDAV) {
[onlyArray addObject:tempCalendar];
}
}
NSPredicate * predicate = [_eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:onlyArray];
NSArray * events = [_eventStore eventsMatchingPredicate:predicate];
return events;
}
通過 event.calendar.allowsContentModifications == YES 可以過濾節(jié)假日、節(jié)氣等系統(tǒng)添加的日歷。
由于我們手動添加的數(shù)據(jù)都是可以手動編輯的,所以event的allowsContentModifications這一只讀屬性剛好可以用到。
4、創(chuàng)建日程并寫入本地日歷
- (void)writeToLocalCalendarAction {
EKEventStore *eventStore = [[EKEventStore alloc] init];
//事件保存到日歷
//06.07 元素
//title(標(biāo)題 NSString),
//location(位置NSString),
//startDate(開始時間 2016/06/07 11:14AM),
//endDate(結(jié)束時間 2016/06/07 11:14AM),
//addAlarm(提醒時間 2016/06/07 11:14AM),
//notes(備注類容NSString)
/// 06.07 時間格式
NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setAMSymbol:@"AM"];
[dateFormatter setPMSymbol:@"PM"];
[dateFormatter setDateFormat:@"hh:mm"];
NSDate *date = [NSDate date];
NSString * s = [dateFormatter stringFromDate:date];
NSLog(@"%@",s);
/// 創(chuàng)建事件
EKEvent *event = [EKEvent eventWithEventStore:eventStore];
event.title = [NSString stringWithFormat:@"寫入日歷事件-%@",s];
event.location = @"北京app";
/// 開始時間(必須傳)
event.startDate = [date dateByAddingTimeInterval:60 * 2];
/// 結(jié)束時間(必須傳)
event.endDate = [date dateByAddingTimeInterval:60 * 5 * 24];
/// event.allDay = YES;//全天
/// 添加提醒
/// 第一次提醒 (幾分鐘后)
[event addAlarm:[EKAlarm alarmWithRelativeOffset:60.0f * -1.0f]];
/// 第二次提醒 ()
/// [event addAlarm:[EKAlarm alarmWithRelativeOffset:60.0f * -10.0f * 24]];
/// 06.07 add 事件類容備注
NSString * str = @"這是備注";
event.notes = [NSString stringWithFormat:@"%@:%@",str,s];
/// 將日歷事件添加到默認的日歷源中
[event setCalendar:[eventStore defaultCalendarForNewEvents]];
/// 保存日歷事件
NSError *err;
[eventStore saveEvent:event span:EKSpanThisEvent error:&err];
}
5、刪除單個日歷和刪除所有日歷
/// 刪除日歷事件(刪除單個)
/// @param eventIdentifier 事件ID(標(biāo)識符)
- (BOOL)deleteCalendarEventIdentifier:(NSString *)eventIdentifier{
EKEvent *event;
NSError*error =nil;
if (eventIdentifier && ![eventIdentifier isEqualToString:@""]) {
event = [self.eventStore eventWithIdentifier:eventIdentifier];
/// commit:NO:最后再一次性提交,YES:當(dāng)前提交
return [self.eventStore removeEvent:event span:EKSpanThisEvent commit:YES error:&error];
// 一次提交所有操作到事件庫
// NSError *errored = nil;
// BOOL commitSuccess = [self.eventStore commit:&errored];
// return commitSuccess;
}
return NO;
}
/// 刪除日歷事件(可刪除一段時間內(nèi)的事件)
/// @param startDate 開始時間
/// @param endDate 結(jié)束時間
- (BOOL)deleteCalendarStartDate:(NSDate *)startDate addEndDate:(NSDate *)endDate {
// 獲取到此事件
NSArray * eventArray = [self.eventStore calendarsForEntityType:EKEntityTypeEvent];
NSMutableArray * onlyArray = [NSMutableArray array];
for (int i=0; i<eventArray.count; i++) {
EKCalendar * tempCalendar = eventArray[i];
EKCalendarType type = tempCalendar.type;
if (type == EKCalendarTypeCalDAV) {
[onlyArray addObject:tempCalendar];
}
}
NSPredicate * predicate = [self.eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:onlyArray];
NSArray * events = [self.eventStore eventsMatchingPredicate:predicate];
for (int i = 0; i < events.count; i ++) {
// 刪除這一條事件
EKEvent *event = events[i];
NSError*error =nil;
// commit:NO:最后再一次性提交
[self.eventStore removeEvent:event span:EKSpanThisEvent commit:NO error:&error];
}
//一次提交所有操作到事件庫
NSError *errored = nil;
BOOL commitSuccess = [self.eventStore commit:&errored];
return commitSuccess;
}
- (EKEventStore *)eventStore {
if (!_eventStore) {
_eventStore = [[EKEventStore alloc]init];
}
return _eventStore;
}
6、修改日歷:
根據(jù)eventIdentifier 查找對應(yīng)日歷,沒找到則重新創(chuàng)建,找如果有先刪除在重新創(chuàng)建。
7、問題解決:
(1)唯一事件id(eventIdentifier)只讀的問題:事件創(chuàng)建之后,系統(tǒng)自動創(chuàng)建eventIdentifier,而我們無法準(zhǔn)確找到對應(yīng)事件的 eventIdentifier。
@property(null_unspecified, nonatomic, readonly) NSString *eventIdentifier;
(2)獲取本地日歷中的日程數(shù)據(jù)數(shù)據(jù)量可能會很大,導(dǎo)致與服務(wù)端返回的新數(shù)據(jù)進行匹配的時候雙重for循環(huán)影響效率。
解決方案:使用allowsContentModifications屬性。由于我們手動添加的數(shù)據(jù)都是可以手動編輯的,所以event的allowsContentModifications這一只讀屬性剛好可以用到??梢詼p少很多系統(tǒng)日歷自帶的event對象,比如節(jié)假日、節(jié)氣等等。
event.calendar.allowsContentModifications == YES
8、其他
(1)基于地理位置的提醒
我們可以設(shè)定當(dāng)用戶進入或離開指定的地理位置區(qū)域時,觸發(fā)日程提醒。例如當(dāng)用戶離開公司,提醒用戶需要到超市購買日用品,作為開發(fā)者,需要確定一個經(jīng)緯度以及一個半徑范圍。
EKAlarm *alarm = [[EKAlarm alloc] init];
EKStructuredLocation *location = [EKStructuredLocation
locationWithTitle:@"Current Location"];
location.geoLocation = [[CLLocation alloc] initWithLatitude:23.1754700000 longitude:113.4147400000];
alarm.structuredLocation = location;
alarm.proximity = EKAlarmProximityEnter;
[event addAlarm:alarm];
參考:
1、iOS 添加項目到系統(tǒng)日歷
2、iOS增、刪、改、查系統(tǒng)提醒事件和日歷事件
3、iOS—EventKit實現(xiàn)app日程同步到本地日歷(唯一id,過濾節(jié)假日)