美文网首页iOS基础
iOS增、删、改、查系统提醒事件和日历事件

iOS增、删、改、查系统提醒事件和日历事件

作者: mian小爬 | 来源:发表于2018-04-12 17:26 被阅读369次

    前言

    1、引入EventKit框架。 (EventKit框架使你能访问用户的Calendar(日历)和Reminder(提醒事项)信息。他们使用相同的库(EKEventStore)处理数据,该库管理所有event数据。该框架除了允许检索用户已经存在的calendar和reminder数据外,还允许创建新的事件和提醒)
    2、将EKEventStore对象写成单例。 (因为需要频繁调用EKEventStore对象,可以将EKEventStore对象写成单例)
    3、设置访问日历的权限NSCalendarsUsageDescription。(iOS10之后,要用到某个权限必须在info.plist里指明,否则会引起崩溃和审核失败)

    检测日历功能是否可以使用

    • 检查授权状态:
    EKAuthorizationStatus eventStatus = [EKEventStore  authorizationStatusForEntityType:EKEntityTypeEvent];
    其中eventStatus为
    EKAuthorizationStatusNotDetermined = 0,// 未进行授权选择
    EKAuthorizationStatusRestricted,//未授权,且用户无法更新,如家长控制情况下
    EKAuthorizationStatusDenied,       // 用户拒绝App使用
    EKAuthorizationStatusAuthorized,   // 已授权,可使用
    
    • 在“未进行授权”的情况下弹出提示框,提示用户授权:
    [self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
          
     }];
    

    完整代码:

    // 检测日历功能是否可以使用
    - (void)checkCalendarCanUsedCompletion:(completion)completion{
    //    EKEntityTypeEvent日历事件
    //    EKEntityTypeReminder提醒事项
        self.completion = completion;
        EKAuthorizationStatus eventStatus = [EKEventStore  authorizationStatusForEntityType:EKEntityTypeEvent];
        if (eventStatus == EKAuthorizationStatusAuthorized) {
            if (self.completion) {
                self.completion(YES, nil);
            }
        }else if(eventStatus == EKAuthorizationStatusNotDetermined){
            __block  BOOL isGranted = NO;
            __block  NSError *isError;
            [self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
                isGranted = granted;
                isError = error;
                if (granted) {
                    NSLog(@"用户点击了允许访问日历");
                }else{
                    NSLog(@"用户没有点允许访问日历");
                }
            }];
            if(self.completion){
                self.completion(isGranted, isError);
            }
        }
    }
    

    .

    添加日历提醒事项

    • 保存日历事件:
    [self.eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&err]; 
    

    commit:yes:表示立即把此次操作提交到系统事件库,NO表示此时不提交。如果一次性操作的事件数比较少的话,可以每次都传YES,实时更新事件数据库。如果一次性操作的事件较多的话,可以每次传NO,最后再执行一次提交所有更改到数据库,把原来的更改全部提交到数据库,不管是添加还是删除。
    EKSpanThisEvent:表示只影响当前事件。 EKSpanFutureEvents 表示影响当前和以后的所有事件。比如某条重复任务修改后保存时,传EKSpanThisEvent表示值修改这一条重复事件。传EKSpanFutureEvents表示修改这一条和以后的所有重复事件。删除事件时,分别表示删除这一条;删除这一条和以后的所有。

    完整代码:

    - (void)createEventCalendarTitle:(NSString *)title addLocation:(NSString *)location addStartDate:(NSDate *)startDate addEndDate:(NSDate *)endDate addAllDay:(BOOL)allDay addAlarmArray:(NSArray *)alarmArray addCompletion:(completion)completion{
        self.completion = completion;
        if ([self.eventStore respondsToSelector:@selector(requestAccessToEntityType:completion:)])
        {
            [self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error){
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (error){
    
                    }else if (!granted){
    
                    }else{
                        EKEvent *event  = [EKEvent eventWithEventStore:self.eventStore];
                        event.title = title;
                        event.location = location;
                        NSDateFormatter *tempFormatter = [[NSDateFormatter alloc]init];
                        [tempFormatter setDateFormat:@"dd.MM.yyyy HH:mm"];
                        event.startDate = startDate;
                        event.endDate   = endDate;
                        // 是否设置全天
                        event.allDay = allDay;
                        //添加提醒
                        if (alarmArray && alarmArray.count > 0) {
                            for (NSString *timeString in alarmArray) {
                                [event addAlarm:[EKAlarm alarmWithRelativeOffset:[timeString integerValue]]];
                            }
                        }
                        //默认日历类型
                        [event setCalendar:[self.eventStore defaultCalendarForNewEvents]];
                        // 保存日历
                        NSError *err;
                        [self.eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
                        if (self.completion) {
                            self.completion(granted,error);
                        }
                    }
                });
            }];
        }
    }
    
        其中EKEvent属性:
        title - 日程的标题
        startDate - 日程的开始日期
        endDate - 日程的结束日期
        calendar - 日程对应的日历
        alarms - 日程的闹钟提醒
        eventIdentifier:唯一标识符区分某个事件,只读
        recurrenceRules - 重复规则,默认不重复
        -  alarms:
        通过event的addAlarm:方法为一个日程添加提醒,指定一个确切时间或一个相对时间。     
        通过removeAlarm: 方法可将提醒移除。
        -  recurrenceRules:
        用initRecurrenceWithFrequency:interval:end:方法创建一个EKRecurrenceRule对象。
        1)EKRecurrenceFrequency类型,指示recurrence是daily、weekly、monthly或yearly.
        2)  interval: 这是一个大于0的整数,来制定重复的间隔。例如,如果recurrence rule是
            weekly,并且recurrence interval是1,然后重复模式为每星期都重复。如果
           recurrence interval是3,那么是每3个星期重复一次。    
        3) end: 这是个可选参数,代表何时终止。
    

    .

    查询日历事件

    • 查询所有的日历事件,包括家庭,工作,生日,中国节假日类型等
    NSArray *tempA = [self.eventStore calendarsForEntityType:EKEntityTypeEvent];
    
    • 谓词查询
    NSPredicate *predicate = [self.eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:only3D];
    // 获取到范围内的所有事件
    NSArray *request = [self.eventStore eventsMatchingPredicate:predicate];
    

    EKEventStore的eventsMatchingPredicate:方法获取属于你提供的谓词中指定的日期范围的所有事件。

    完整代码
    (modifytitle : 有值则查询此日期内标题为modifytitle的日历事件,无则查询此日期内全部日历事件)

    // 查日历事件:startDate/endDate : 开始/结束时间 modifytitle:标题,为空则都要查询
    - (NSArray *)checkToStartDate:(NSDate *)startDate addEndDate:(NSDate *)endDate addModifytitle:(NSString *)modifytitle{
        // 查询到所有的日历
        NSArray *tempA = [self.eventStore calendarsForEntityType:EKEntityTypeEvent];
        NSMutableArray *only3D = [NSMutableArray array];
        for (int i = 0 ; i < tempA.count; i ++) {
            EKCalendar *temCalendar = tempA[i];
            EKCalendarType type = temCalendar.type;
            // 工作、家庭和本地日历
            if (type == EKCalendarTypeLocal || type == EKCalendarTypeCalDAV) {
                [only3D addObject:temCalendar];
            }
        }
        NSPredicate *predicate = [self.eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:only3D];
        // 获取到范围内的所有事件
        NSArray *request = [self.eventStore eventsMatchingPredicate:predicate];
        // 按开始事件进行排序
        request = [request sortedArrayUsingSelector:@selector(compareStartDateWithEvent:)];
        if (!modifytitle || [modifytitle isEqualToString:@""]) {
           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;
        }
    }
    

    .

    删除日历事件

    • 删除日历事件
    // commit:NO:最后再一次性提交
     [self.eventStore removeEvent:event span:EKSpanThisEvent commit:NO error:&error];
    
    • 一次提交所有操作到事件库
    NSError *errored = nil;
    BOOL commitSuccess= [self.eventStore commit:&errored];
    return commitSuccess;
    

    完整代码:

    // 删除日历事件
    - (BOOL)deleteCalendarStartDate:(NSDate *)startDate addEndDate:(NSDate *)endDate addModifytitle:(NSString *)modifytitle{
        // 获取到此事件
        NSArray *request = [self checkToStartDate:startDate addEndDate:endDate addModifytitle:modifytitle];
        
        for (int i = 0; i < request.count; i ++) {
            // 删除这一条事件
            EKEvent *event = request[i];
            [event setCalendar:[self.eventStore defaultCalendarForNewEvents]];
            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;
    }
    

    .

    修改日历事件

    查询是否有此日历,没有则添加,有则先删除后添加来实现修改
    完整代码

    // 修改日历
    - (void)modifyCalendarCalendarTitle:(NSString *)title addLocation:(NSString *)location addModifytitle:(NSString *)modifytitle addStartDate:(NSDate *)startDate addEndDate:(NSDate *)endDate addAllDay:(BOOL)allDay addAlarmArray:(NSArray *)alarmArray addCompletion:(completion)completion{
        // 获取到此事件
        NSArray *request = [self checkToStartDate:startDate addEndDate:endDate addModifytitle:modifytitle];
        if (request.count > 0 ) {
            for (int i = 0; i < request.count; i++) {
                [self deleteCalendarStartDate:startDate addEndDate:endDate addModifytitle:modifytitle];
            
                [self createEventCalendarTitle:title addLocation:location addStartDate:startDate addEndDate:endDate addAllDay:allDay addAlarmArray:alarmArray addCompletion:completion];
            }
        }else{
            // 没有此条日历
            [self createEventCalendarTitle:title addLocation:location addStartDate:startDate addEndDate:endDate addAllDay:allDay addAlarmArray:alarmArray addCompletion:completion];
        }
    }
    

    工具类(ViewController是注释掉的例子)
    WMEventCalendarDemo

    相关文章

      网友评论

        本文标题:iOS增、删、改、查系统提醒事件和日历事件

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