下面我們討論如何在iOS中創建日歷事件。日歷事件主要涉及到EventKit框架。
首先我們需要對工程添加框架。點擊工程查看屬性,在Linked FrameWorks and Libraries中增加EventKit框架,並且將EventKit通過鼠標拖動移動到Frameworks文件夾:
下面我們去創建一個按鈕事件。
[cpp] view plaincopy
- - (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以上版本中,我們需要對訪問權限進行授權,所以我們需要做以下操作。頭文件中:
[cpp] view plaincopy
- #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
.m文件:
[cpp] view plaincopy
- #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
以上是個簡單的例子,下面我們看一個更復雜的代碼。
建立項目
- 我們建立一個Master-Detail類型的工程,使用Storyboard。
- 這次我們添加兩個Framework,分別是EventKit和EventKitUI。
- 第一個頁面使用TableViewController,用於展現事件列表。
- 第二個頁面使用ViewController,用於展現事件描述;
- 注意在AppDelegate.m中添加:
[cpp] view plaincopy
- @synthesize window;
[cpp] view plaincopy
- //
- // 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。