Call system calendar in iOS - <EventKit/EventKit.h> and utility classes (below)

Keywords: iOS Database Google

1. First, a brief understanding of EventKit http://docs.xamarin.com/guides/ios/platform_features/introduction_to_eventkit/

Summary

IOS has two built-in calendar applications: Calendar and Reminders. It is obvious that Calendar manages calendar data, while Reminders is not particularly obvious. Reminders have dates for events scheduled, completed, and so on. For example, iOS stores all the calendar data, whether it belongs to calendar events or reminders, they belong to the Calendar Database.

The EventKit framework provides a way to access calendars, calendar events, and alert data stored in the Calendar Database. IOS 4 has supported access to calendars and calendar events since its inception, while iOS 6 has added support for access reminders.

Necessary condition

EventKit was proposed in iOS 4.0, but Reminders were proposed in iOS 6. In this way, EventKit development is usually done. Calendar use is based on iOS 4.0, and reminders need to be based on iOS 6.

In addition, Reminders applications are not suitable for simulators, which means that reminder data is not available unless you add them first. Also, assessment requests are only presented to users on real devices. In this way, EventKit development is based on real devices for testing.

Event Kit Foundation

When we use EventKit, it's important to master common classes and their usage. All classes can be found in MonotoTouch. EventKit and MonotoTouch. EventKit UI (for the EKEvent Edit Controller).

EventStore

EventStore is the most important class in EventKit, because it is required for any operation performed in EventKit. EventStore can be considered as persistent storage or database, the engine of EventKit data. From EventStore, you can access calendars and calendar events in Calendar applications, as well as reminders in Reminders applications.

Because EventStore is very much like a database engine, it should be held for a long time, which means that it should be created and destroyed as little as possible in the life cycle of the application. In practice, it's recommended that once you create an EventStore in your application, you should keep its reference throughout the application's life cycle unless you are sure you don't use it anymore. In addition, all calls are directed at an EventStore instance of the fish. So, we recommend the singleton model.

Creating an Event Store

The following code illustrates a simple and effective way to create an EventStore singleton that will remain static in the application.

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 ( );
    }
}

The above code implements the EventStore object using the singleton mode when loading the application. This object can be accessed globally, for example:

App.Current.EventStore;
Request calendar and alert data

Before allowing access to any data through EventStore, the application must first obtain permissions, whether calendar event s or reminders data, depending on you. To this end, EventStore exposes a method called RequestAccess, when it is called, the system will pop up a prompt box to the user, telling the user application to request access to calendar data or reminder data. Because of the prompt box, the call is asynchronous, and when completed, a callback with two parameters (a bool type granted and NSError) is called to indicate whether permission access is obtained.

The following code is to request permission to access calendar events:


 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 ();
                 } );

Once the request is allowed, the application will not be prompted again if it is installed on the device. However, permissions only allow access to the given resource type, which is a calendar event or reminder. If an application needs access to both, it needs to request.

Because permissions are cached, it's relatively easy to request each time, so it's a good idea to request permissions before every operation.

In addition, because callback methods are invoked in non-UI threads, all operations to update the UI must be invoked in Main Thread, otherwise an exception will be thrown.

EKEntityType

This is an enumeration type that describes the type of EventKit or data. It has two values: Event and Reminder. It is used in many ways, including EventStore's RequestAccess method, to tell EventKit what type of data permissions to obtain.

EKCalendar

EKCalendar is the equivalent of a calendar that contains a set of calendar events that can be stored in many places, such as local, iCloud, third-party vendors: Exchange Sever or Google. Most of the time, EKCalendar is used to tell EventKit where to find and store events.

EKEventEditController

EKEventEditController can be found in MonoTouch.EventKitUI, which is a built-in controller for creating modified calendar events. It's like a built-in camera controller, and EKEvent Edit Controller helps you do heavy UI work and save data.

EKEvent

EKEvent is equivalent to a calendar. Either EKEvent or EKReminder inherits from EKCalendar Item. They all have fields such as Title and Notes.

EKReminder
EKReminder is equivalent to a reminder.
EKSpan

EKSpan is an enumerated value used to describe the span of events when modifying events to be repeatable. It has two values: ThisEvent and FutureEvents. This Event means that any change will occur only in a series of specific events cited, while FutureEvents will affect events and all future recurrences.

Here's the actual code:

#import <Foundation/Foundation.h>

@interface EventCalendar : NSObject

+ (instancetype)sharedEventCalendar;

/**
*  Add App event to system calendar reminder to realize alarm reminder function
*
*  @param title      Event title
*  @param location   Event location
*  @param startDate  start time
*  @param endDate    End time
*  @param allDay     Is it all day?
*  @param alarmArray Alarm clock set
*  @param block      callback
*/
- (void)createEventCalendarTitle:(NSString *)title location:(NSString *)location startDate:(NSDate *)startDate endDate:(NSDate *)endDate allDay:(BOOL)allDay alarmArray:(NSArray *)alarmArray;

@end

#import "EventCalendar.h"
#import <EventKit/EventKit.h>
#import <UIKit/UIKit.h>

@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:@"Failed to add, please try again later"];
    
                }else if (!granted){
                    [strongSelf showAlert:@"Calendar is not allowed,Please allow this in the settings App Using calendar"];
                    
                }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;
                    
                    //Add reminder
                    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:@"Added to System Calendar"];
           
                }
            });
        }];
    }
}

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

@end


Note here: If you need to alert the user before the time occurs, you need to pass in the alert time array, which is calculated in seconds. For example, the day before the time occurred, the elements of the time array are: - 86400; calculate it yourself!!!

Posted by help_lucky on Tue, 11 Dec 2018 15:33:05 -0800