iOS中调用系统日历 - 和实用类(在下面)

1.首先简单了解 EventKit ---- 摘自http://docs.xamarin.com/guides/ios/platform_features/introduction_to_eventkit/

概述

iOS有两个内建的日历应用:Calendar,Reminders。很显然能看出Calendar是管理日历数据的,而Reminders却不是特别显而易见。Reminders拥有在指定时间安排、完成等等的事件的日期。比如,iOS存储着所有的日历数据,无论它属于日历事件(calendar events)或者提醒(reminders),他们都属于日历数据库(Calendar Database)。

EventKit框架提供了一种访问存储在日历数据库(Calendar Database)的日历、日历事件、提醒数据的方式。iOS4开始就支持访问日历和日历事件、而iOS6起增加支持访问提醒。

必要条件

EventKit是在iOS4.0提出的,但访问提醒(Reminders)是在iOS6中提出。这样的话,通常做EventKit 开发,使用日历要基于iOS4.0,提醒需要基于iOS6。

另外,Reminders应用程序不适用于模拟器,这意味着提醒数据是不可以用的,除非你先添加了他们。还有,访问请求(assess requests)只在真实设备上展示给用户。这样的话,EventKit开发要基于真实设备来测试。

Event Kit 基础

当我们使用EventKit的时候,重要的是掌握常用类和他们的用法。所有的类(Class)都可以在MonoTouch.EventKit 和 MonoTouch.EventKitUI(for the EKEventEditController)中找到.

EventStore

EventStore是EventKit中最重要的类,因为在EventKit中执行的任何操作都需要它。EventStore可以认为是 持久存储器 或者 数据库,EventKit数据的引擎。从EventStore中,你可以访问到Calendar应用程序中得日历还有日历事件,当然还有Reminders应用中得提醒。

因为EventStore很像一个数据库引擎,所以他应该长久持有,这意味着在应用的生命周期内它应该尽可能的少创建、销毁。实际,建议这样:一旦你在应用中创建了一个EventStore,你应该在应用的生命周期内保持它(EventStore)的引用,除非你确定你再不使用它了。另外,所有的调用都针对鱼一个EventStore实例。所以呢,推荐单例模式。

Creating an Event Store

下面的代码,说明了一个简单而有效方式创建一个EventStore的单例,使它在应用中静态存在。

public class App

{
    public static App Current {

            get { return current; }

    }

    private static App current;

    public EKEventStore EventStore {
            get { return eventStore; }
    }
    protected EKEventStore eventStore;

    static App ()
    {
            current = new App();
    }
    protected App () 
    {
            eventStore = new EKEventStore ( );
    }
}

上面的代码在应用加载的时候 使用了单例模式实现了EventStore对象。这个对象能够全局访问,例如:

App.Current.EventStore;
请求 日历 和 提醒 数据

在允许通过EventStore访问任何数据之前,应用程序必须首先获取权限,无论日历事件(calendar event)还是 提醒数据(reminders data),取决于你。为此,EventStore暴露了一个方法RequestAccess,当调用它的时候,系统会弹出一个提示框给用户,告诉用户应用程序请求访问日历数据或者提醒数据。因为有提示框,所以这个调用是异步的,并且完成后会有一个带两个参数(一个bool类型的granted和 NSError)的回调被调用,指出是否获取到权限访问。

下面代码就是请求权限访问日历事件:


 App.Current.EventStore.RequestAccess (EKEntityType.Event, 
         (bool granted, NSError e) => {
                 if (granted)
                         //do something here
                 else
                         new UIAlertView ( "Access Denied", "User Denied Access to Calendar Data", null,"ok", null).Show ();
                 } );

一旦请求被允许,这个应用只要安装在设备上,那么就不会在被弹出再提示。但是,权限只是允许访问给出的资源类型,是日历事件或提醒。如果一个应用需要这两种都能访问,那就都要请求。

因为权限是被缓存的了,那么每次请求相对轻松,所以在每个操作之前都请求权限是个不错的主意。

另外,因为回调方法是在非UI线程中调用的,所以所有更新UI得操作都要在Main Thread调用,否则就会引发异常。

EKEntityType

这是个描述EventKit或者数据的类型 的枚举类型,它有两个值:Event、Reminder。它在很多方法中被使用,包括EventStore的RequestAccess方法,告诉EventKit要获取什么类型的数据权限。

EKCalendar

EKCalendar相当于一个日历,包含了一组日历事件,日历能够存储在很多地方,例如 本地、iCloud、第三方商:Exchange Sever 或者Google。大多时候,EKCalendar被用来告知EventKit,事件从何查找,存储到哪里。

EKEventEditController

EKEventEditController能够在MonoTouch.EventKitUI中找到,它是个内建的控制器,用于创建修改日历事件。这很像内建的相机控制器,EKEventEditController帮你做了繁重的UI和保存数据的工作。

EKEvent

EKEvent相当于一个日历,不管是EKEvent还是EKReminder都继承于EKCalendarItem,他们都有Title、Notes等字段。

EKReminder
EKReminder相当于一个提醒事项。
EKSpan

EKSpan是个当修改事件为可重复的时候用于描述事件的跨度的枚举值,它有两个值:ThisEvent、FutureEvents。ThisEvent意味着任何改变,只会发生在被引用的一系列特定事件,而FutureEvents会影响事件和所有未来的复发。

下面来点实际的代码:

#import 

@interface EventCalendar : NSObject

+ (instancetype)sharedEventCalendar;

/**
*  将App事件添加到系统日历提醒事项,实现闹铃提醒的功能
*
*  @param title      事件标题
*  @param location   事件位置
*  @param startDate  开始时间
*  @param endDate    结束时间
*  @param allDay     是否全天
*  @param alarmArray 闹钟集合
*  @param block      回调方法
*/
- (void)createEventCalendarTitle:(NSString *)title location:(NSString *)location startDate:(NSDate *)startDate endDate:(NSDate *)endDate allDay:(BOOL)allDay alarmArray:(NSArray *)alarmArray;

@end

#import "EventCalendar.h"
#import 
#import 

@implementation EventCalendar

static EventCalendar *calendar;

+ (instancetype)sharedEventCalendar{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        calendar = [[EventCalendar alloc] init];
    });
    
    return calendar;
}

+(instancetype)allocWithZone:(struct _NSZone *)zone{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        calendar = [super allocWithZone:zone];
    });
    return calendar;
}

- (void)createEventCalendarTitle:(NSString *)title location:(NSString *)location startDate:(NSDate *)startDate endDate:(NSDate *)endDate allDay:(BOOL)allDay alarmArray:(NSArray *)alarmArray{
    __weak typeof(self) weakSelf = self;
    
    EKEventStore *eventStore = [[EKEventStore alloc] init];
    
    if ([eventStore respondsToSelector:@selector(requestAccessToEntityType:completion:)])
    {
        [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error){
            
            dispatch_async(dispatch_get_main_queue(), ^{
                __strong typeof(weakSelf) strongSelf = weakSelf;
                if (error)
                {
                    [strongSelf showAlert:@"添加失败,请稍后重试"];
    
                }else if (!granted){
                    [strongSelf showAlert:@"不允许使用日历,请在设置中允许此App使用日历"];
                    
                }else{
                    EKEvent *event  = [EKEvent eventWithEventStore: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:[eventStore defaultCalendarForNewEvents]];
                    NSError *err;
                    [eventStore saveEvent:event span:EKSpanThisEvent error:&err];
                    [strongSelf showAlert:@"已添加到系统日历中"];
           
                }
            });
        }];
    }
}

- (void)showAlert:(NSString *)message
{
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
    [alert show];
}

@end


这里需要注意的地方 :如果需要在时间发生前提醒用户,需要传入提醒时间数组,这个数组是按照秒计算的。比如时间发生前一天提醒,时间数组的元素就是:-86400;自己计算一下喽!!!

你可能感兴趣的:(iOS中调用系统日历 - 和实用类(在下面))