iOS系統(tǒng)日歷的獲取、創(chuàng)建、刪除和修改

1、Info.plist 中添加獲取系統(tǒng)日歷權(quán)限提醒

Privacy - Calendars Usage Description / 有助于您更好的管理日程


權(quán)限添加
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é)假日)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容