美文网首页iOS常用
iOS系统日历的获取、创建、删除和修改

iOS系统日历的获取、创建、删除和修改

作者: wuyukobe | 来源:发表于2021-05-19 19:34 被阅读0次
    1、Info.plist 中添加获取系统日历权限提醒

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


    权限添加
    2、获取权限
    /**
     EKAuthorizationStatusNotDetermined = 0,// 未进行授权选择
     EKAuthorizationStatusRestricted,//未授权,且用户无法更新,如家长控制情况下
     EKAuthorizationStatusDenied,       // 用户拒绝App使用
     EKAuthorizationStatusAuthorized,   // 已授权,可使用
     */
    -(BOOL)getLocalCalendarAuthorization{
        _eventStore = [[EKEventStore alloc]init];
        EKAuthorizationStatus eventStatus = [EKEventStore  authorizationStatusForEntityType:EKEntityTypeEvent];
        __block BOOL allow = NO;
        if(eventStatus ==EKAuthorizationStatusNotDetermined){
            //用户尚未授权,提示用户授权。下边的requestAccessToEntityType:方法可以调出系统授权弹窗
            [_eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
                if (granted) {
                    //允许
                    allow = YES;
                }else{
                    //不允许
                    allow = NO;
                }
            }];
        }else if(eventStatus ==EKAuthorizationStatusAuthorized){
            //用户已经允许授权。作相应处理,比如查询日历里今天的所有事件..
            allow = YES;
        }
        return allow;
    }
    
    3、获取所有的系统本地日历
    /// 获取系统本地日历事件
    - (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 可以过滤节假日、节气等系统添加的日历。
    由于我们手动添加的数据都是可以手动编辑的,所以event的allowsContentModifications这一只读属性刚好可以用到。

    4、创建日程并写入本地日历
    - (void)writeToLocalCalendarAction {
        EKEventStore *eventStore = [[EKEventStore alloc] init];
    
        //事件保存到日历
        //06.07 元素
        //title(标题 NSString),
        //location(位置NSString),
        //startDate(开始时间 2016/06/07 11:14AM),
        //endDate(结束时间 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);
        
        /// 创建事件
        EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
        event.title  = [NSString stringWithFormat:@"写入日历事件-%@",s];
        event.location = @"北京app";
        
        /// 开始时间(必须传)
        event.startDate = [date dateByAddingTimeInterval:60 * 2];
        /// 结束时间(必须传)
        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(标识符)
    - (BOOL)deleteCalendarEventIdentifier:(NSString *)eventIdentifier{
        EKEvent *event;
        NSError*error =nil;
        if (eventIdentifier && ![eventIdentifier isEqualToString:@""]) {
            event = [self.eventStore eventWithIdentifier:eventIdentifier];
            /// commit:NO:最后再一次性提交,YES:当前提交
            return [self.eventStore removeEvent:event span:EKSpanThisEvent commit:YES error:&error];
    //        一次提交所有操作到事件库
    //        NSError *errored = nil;
    //        BOOL commitSuccess = [self.eventStore commit:&errored];
    //        return commitSuccess;
        }
        return NO;
    }
    
    /// 删除日历事件(可删除一段时间内的事件)
    /// @param startDate 开始时间
    /// @param endDate 结束时间
    - (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、修改日历:

    根据eventIdentifier 查找对应日历,没找到则重新创建,找如果有先删除在重新创建。

    7、问题解决:

    (1)唯一事件id(eventIdentifier)只读的问题:事件创建之后,系统自动创建eventIdentifier,而我们无法准确找到对应事件的 eventIdentifier。

    @property(null_unspecified, nonatomic, readonly) NSString *eventIdentifier;
    

    (2)获取本地日历中的日程数据数据量可能会很大,导致与服务端返回的新数据进行匹配的时候双重for循环影响效率。
    解决方案:使用allowsContentModifications属性。由于我们手动添加的数据都是可以手动编辑的,所以event的allowsContentModifications这一只读属性刚好可以用到。可以减少很多系统日历自带的event对象,比如节假日、节气等等。

    event.calendar.allowsContentModifications == YES
    
    8、其他

    (1)基于地理位置的提醒
    我们可以设定当用户进入或离开指定的地理位置区域时,触发日程提醒。例如当用户离开公司,提醒用户需要到超市购买日用品,作为开发者,需要确定一个经纬度以及一个半径范围。

    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 添加项目到系统日历
    2、iOS增、删、改、查系统提醒事件和日历事件
    3、iOS—EventKit实现app日程同步到本地日历(唯一id,过滤节假日)

    相关文章

      网友评论

        本文标题:iOS系统日历的获取、创建、删除和修改

        本文链接:https://www.haomeiwen.com/subject/uvwpjltx.html