下面我们讨论如何在iOS中创建日历事件。日历事件主要涉及到EventKit框架。
首先我们需要对工程添加框架。点击工程查看属性,在Linked FrameWorks and Libraries中增加EventKit框架,并且将EventKit通过鼠标拖动移动到Frameworks文件夹:
下面我们去创建一个按钮事件。
- (IBAction)addEvent:(id)sender { // create a new Event EKEvent *event = [EKEvent eventWithEventStore: store]; // create start date & end date NSDate *startDate = [[NSDate alloc] init]; NSDate *endDate = [[NSDate alloc] init]; // set event's properties [event setTitle: @"an insert title"]; [event setStartDate: startDate]; [event setEndDate: endDate]; [event setAllDay: YES]; // insert new event into the default calendar EKCalendar *calendar = [store defaultCalendarForNewEvents]; [event setCalendar: calendar]; // create an NSError pointer NSError *err = nil; // save event [store saveEvent:event span:EKSpanThisEvent error:&err]; if (err == nil) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Congratulations" message:@"event create success." delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil]; [alert show]; } else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failed" message:@"event create failed." delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil]; [alert show]; } }
在iOS 6以上版本中,我们需要对访问权限进行授权,所以我们需要做以下操作。头文件中:
#import <UIKit/UIKit.h> #import <EventKit/EventKit.h> @interface ViewController : UIViewController - (IBAction)addEvent:(id)sender; @property EKEventStore *store; @property (strong, nonatomic) IBOutlet UIButton *myTestButton; @end
#import "ViewController.h" @interface ViewController () @end @implementation ViewController @synthesize store; @synthesize myTestButton; - (void)viewDidLoad { [super viewDidLoad]; // get Event Store store = [[EKEventStore alloc] init]; [self requestCalendarAccess]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } // This method is called when the user has granted permission to Calendar -(void)accessGrantedForCalendar { // Update the UI with the above events [myTestButton setEnabled:YES]; } // Prompt the user for access to their Calendar -(void)requestCalendarAccess { [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) { if (granted) { // Let's ensure that our code will be executed from the main queue dispatch_async(dispatch_get_main_queue(), ^{ [self accessGrantedForCalendar]; }); } }]; } @end
以上是个简单的例子,下面我们看一个更复杂的代码。
@synthesize window;
// // MasterViewController.m // EventManager // // Created by Sam Wang on 13-7-24. // Copyright (c) 2013年 cn.impressmedia. All rights reserved. // #import "MasterViewController.h" #import "DetailViewController.h" @interface MasterViewController () { // NSMutableArray *_objects; } @end @implementation MasterViewController; @synthesize store; @synthesize eventArray; @synthesize canDealWithEvent; - (void)awakeFromNib { [super awakeFromNib]; } // 请求获取日历应用的部分权限 -(void)requestCalendarAccess { [store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) { if (granted) { dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"gain event access"); self.canDealWithEvent = YES; }); } else { dispatch_sync(dispatch_get_main_queue(), ^{ NSLog(@"we haven't got any event access, so we can do nothing except exit."); self.canDealWithEvent = NO; }); } }]; } // 刷新事件数组 -(void)refreshEventArray { if (canDealWithEvent == YES) { return ; } // 从现在开始 NSDate *startDate = [NSDate date]; // 从现在开始的一个月时间 NSDateComponents *tomorrowDateComponents = [[NSDateComponents alloc] init]; // day year,等等均可设置 tomorrowDateComponents.month = 1; NSDate *endDate = [[NSCalendar currentCalendar] dateByAddingComponents:tomorrowDateComponents toDate:startDate options:0]; // 仅搜索默认日历对象 NSArray *calendarArray = [NSArray arrayWithObject:self.store.defaultCalendarForNewEvents]; NSPredicate *predicate = [self.store predicateForEventsWithStartDate:startDate endDate:endDate calendars:calendarArray]; // 搜索满足断言的事件 eventArray = [NSMutableArray arrayWithArray:[self.store eventsMatchingPredicate:predicate]]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. canDealWithEvent = NO; store = [[EKEventStore alloc] init]; [self requestCalendarAccess]; [self refreshEventArray]; self.navigationItem.leftBarButtonItem = self.editButtonItem; UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)]; self.navigationItem.rightBarButtonItem = addButton; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)insertNewObject:(id)sender { if (!eventArray) { eventArray = [[NSMutableArray alloc] init]; } // create a new Event EKEvent *event = [EKEvent eventWithEventStore: store]; // create start date & end date NSDate *startDate = [[NSDate alloc] init]; NSDate *endDate = [[NSDate alloc] init]; // set event's properties [event setTitle: @"new event"]; [event setStartDate: startDate]; [event setEndDate: endDate]; [event setAllDay: YES]; // insert new event into the default calendar EKCalendar *calendar = [store defaultCalendarForNewEvents]; [event setCalendar: calendar]; // create an NSError pointer NSError *err = nil; // save event [store saveEvent:event span:EKSpanThisEvent error:&err]; if (err == nil) { NSLog(@"insert event success."); [eventArray insertObject:[NSDate date] atIndex:0]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:(eventArray.count - 1) inSection:0]; [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else { NSLog(@"insert failed."); } } #pragma mark - Table View - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [eventArray count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; // NSDate *object = eventArray[indexPath.row]; // cell.textLabel.text = [object description]; EKEvent *event = eventArray[indexPath.row]; cell.textLabel.text = [event title]; return cell; } - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the specified item to be editable. return YES; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [eventArray removeObjectAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. } } /* // Override to support rearranging the table view. - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { } */ /* // Override to support conditional rearranging of the table view. - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the item to be re-orderable. return YES; } */ - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([[segue identifier] isEqualToString:@"showDetail"]) { NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; NSDate *object = eventArray[indexPath.row]; [[segue destinationViewController] setDetailItem:object]; } } @end
apple的示例代码参见:SimpleEKDemo。