How to prefill title and location for created event in EKEventEditViewController?
Should I create EKEvent programmatically first, and then edit it? In this case how to delete it if user touched cancel?
When you have set the eventStore property into the EKEventEditViewController, it will have created its own event. You can edit that before you display the EKEventEditViewController.
The answer is: create EKEvent programmatically first, and then edit it.
It works.
Create the event first, then edit it.
EKEvent *event = [EKEvent eventWithEventStore:eventStore];
event.startDate = lastSelectedDate; // your selected start date
event.endDate = [lastSelectedDate dateByAddingTimeInterval:60*60*2]; // your selected end date
// Creating event controller
EKEventEditViewController *eventViewController = [[EKEventEditViewController alloc] init];
eventViewController.editViewDelegate = self;
eventViewController.eventStore = eventStore;
// Set event
eventViewController.event = event;
[self presentViewController:eventViewController animated:YES completion:nil];
Related
My calendar is working perfectly I show events from calendar in my tapku calendar and I can also edit them so for editing I am using EKEventEditViewController so when editing is completed then
- (void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action
get called and this is how I try to update My calendar here
TKCalendarMonthViewController *tk = [[TKCalendarMonthViewController alloc]init];
[tk loadView];
loadview method is as below and now I will explain whats wrong in comment
this method get called when My calendar is loading. So for loading it again I am calling this method again
- (void) loadView{
[super loadView];
_monthView = [[TKCalendarMonthView alloc] initWithSundayAsFirst:_sundayFirst];
_monthView.delegate = self;
_monthView.dataSource = self;
NSLog(#"::%#",_monthView.dataSource);
NSLog(#"::%#",_monthView.delegate);
[self.view addSubview:_monthView];
[_monthView reload]; // reload method get called
}
- (void) reload{
NSArray *dates = [TKCalendarMonthTiles rangeOfDatesInMonthGrid:[currentTile monthDate] startOnSunday:sunday];
NSLog(#"%#",dates);
NSLog(#"%#",self.dataSource);
// below calendarMonthView:self method get called when my cal is getting called first time by it self but when i try by creating object of class like i showed in that delegate method then below method is not getting called and this is why my cal is not getting updated
// SO THE PROBLEM IS THIS METHOD IS NOT GETTING CALLED
NSArray *ar = [self.dataSource calendarMonthView:self marksFromDate:[dates objectAtIndex:0] toDate:[dates lastObject]];
TKCalendarMonthTiles *refresh = [[TKCalendarMonthTiles alloc] initWithMonth:[currentTile monthDate] marks:ar startDayOnSunday:sunday];
[refresh setTarget:self action:#selector(tile:)];
[self.tileBox addSubview:refresh];
[currentTile removeFromSuperview];
currentTile = refresh;
}
All NSLog's are prints with values non of them is null.
#property (strong,nonatomic) TKCalendarMonthView *monthView;
[self.monthView reload];
note: do not #synthesize property
In my Background method, i scheduled the two notification as follow.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
localNotification = [[UILocalNotification alloc] init]; //Create the localNotification object which is declared in appDelegate.h
[localNotification setFireDate:[NSDate dateWithTimeIntervalSinceNow:[datePicker countDownDuration]]]; //Set the date when the alert will be launched using the date adding the time the user selected on the timer
[localNotification setAlertAction:#"Launch"]; //The button's text that launches the application and is shown in the alert
[localNotification setAlertBody:[alertBodyField text]]; //Set the message in the notification from the textField's text
[localNotification setHasAction: YES]; //Set that pushing the button will launch the application
[localNotification setApplicationIconBadgeNumber:[[UIApplication sharedApplication] applicationIconBadgeNumber]+1]; //Set the Application Icon Badge Number of the application's icon to the current Application Icon Badge Number plus 1
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification]; //Schedule the notification with the system
// ** Notification 2***
localNotification2 = [[UILocalNotification alloc] init]; //Create the localNotification object which is declared in appDelegate.h
[localNotification2 setFireDate:[NSDate dateWithTimeIntervalSinceNow:[datePicker countDownDuration]]]; //Set the date when the alert will be launched using the date adding the time the user selected on the timer
[localNotification2 setAlertAction:#"Launch"]; //The button's text that launches the application and is shown in the alert
[localNotification2 setAlertBody:[alertBodyField text]]; //Set the message in the notification from the textField's text
[localNotification2 setHasAction: YES]; //Set that pushing the button will launch the application
[localNotification2 setApplicationIconBadgeNumber:[[UIApplication sharedApplication] applicationIconBadgeNumber]+1]; //Set the Application Icon Badge Number of the application's icon to the current Application Icon Badge Number plus 1
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification2]; //Schedule the notification with the system
}
It works fine for coming the notification.
Question
How can I detect which notification is come in didreceivenotification method??
Because I want to do the different task based on the notification came.
You can set the userInfo Dictionary
localNotification1 = [[UILocalNotification alloc] init];
localNotification1.userInfo = #{ "type" : #1 };
...
localNotification2 = [[UILocalNotification alloc] init];
localNotification2.userInfo = #{ "type" : #2 };
...
...
you can set a NSDictionary in userInfo property of a UILocalNotification
So you can do it this way...
localNotification1.userInfo = [NSDictionary dictionaryWithObject:#"1" forKey:#"NO"];
localNotification1.userInfo = [NSDictionary dictionaryWithObject:#"2" forKey:#"NO"];
and compare the key "NO" in didReceiveNotification.
I'm working with the EventKit Framework. It is working almost perfect but I have still some issues. When I push my on an Event, it goes to the details of that Event. It shows correctly the details and I can also edit and save it. The problem is with the navigation bar.
It shows the titles inside the navigation bar.These titles are Event Details and Edit. Also it is not showing a backbutton, to go back to my calendar. What I also should mention is that I'm using the Kal Calendar framework.
I'm pushing to de detailsViewController like this.
Appointment *appointment = [dataSource appointmentAtIndexPath:indexPath];
// Upon selecting an event, create an EKEventViewController to display the event.
self.detailViewController = [[EKEventViewController alloc] initWithNibName:nil bundle:nil];
self.detailViewController.title = #"";
detailViewController.event = appointment.event;
// Allow event editing.
detailViewController.allowsEditing = YES;
[calendar.navigationController pushViewController:detailViewController animated:YES];
And this is how my delegate looks like
// Overriding EKEventEditViewDelegate method to update event store according to user actions.
- (void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action {
NSError *error = nil;
EKEvent *thisEvent = controller.event;
controller.title = #"";
switch (action) {
case EKEventEditViewActionCanceled:
// Edit action canceled, do nothing.
break;
case EKEventEditViewActionSaved:
// When user hit "Done" button, save the newly created event to the event store,
// and reload table view.
// If the new event is being added to the default calendar, then update its
// eventsList.
if (self.defaultCalendar == thisEvent.calendar) {
[self.eventsList addObject:thisEvent];
}
[controller.eventStore saveEvent:controller.event span:EKSpanThisEvent error:&error];
//[calendar reloadData];
break;
case EKEventEditViewActionDeleted:
// When deleting an event, remove the event from the event store,
// and reload table view.
// If deleting an event from the currenly default calendar, then update its
// eventsList.
if (self.defaultCalendar == thisEvent.calendar) {
[self.eventsList removeObject:thisEvent];
}
[controller.eventStore removeEvent:thisEvent span:EKSpanThisEvent error:&error];
//[calendar reloadData];
break;
default:
break;
}
// Dismiss the modal view controller
[controller dismissModalViewControllerAnimated:YES];
}
// Set the calendar edited by EKEventEditViewController to our chosen calendar - the default calendar.
- (EKCalendar *)eventEditViewControllerDefaultCalendarForNewEvents:(EKEventEditViewController *)controller {
EKCalendar *calendarForEdit = self.defaultCalendar;
return calendarForEdit;
}
I came up with this solution:
EKEventEditViewController * controller = [[EKEventEditViewController alloc] init];
controller.eventStore = self.eventStore;
controller.event = result;
controller.title = #"";
controller.navigationItem.title = #"";
controller.navigationItem.titleView = [UIView new];
NSArray * array =controller.navigationBar.items;
UINavigationItem * titleItem = array.firstObject;
titleItem.title = #"";
controller.editViewDelegate = (id)self;
[self presentViewController:controller animated:YES completion:NULL];
The EKEventEditViewController is not embedded in a navigation controller, it has its own UINavigationBar, I keep the navigation item if Apple will change this in the future and embed it in a navigation controller.
i think you have added navigation item on the storyboard or nib file. remove it.
make self.title=nil; or self.title=#"";
I am using the Kal calendar in my app, (hopefully that doesn't change too much) but I get an EKEvent object from that depending on the user selection on the calendar.
Anyway, how can I edit and delete an event which already exists? Namely the EKEvent that I receive?
I need to do this all programatically, I am not using any of Apple's pre-made EKEventViewController's.
I can successfully create and save new events, but Im unsure of how to edit or delete existing ones, any help would be appreciated, thanks.
A complete answer would almost require a demo project.
Other approach would be simply giving you a link to Event Kit Programming Guide.
Since you did not provide any code (what you have tried already) i hope this extract from a working app will push you to the right track.
Note that i sublassed EKEventViewController due to app's specifics - this is not neccessary. I had to sublass it simply because original EKEventViewController
didn't spawn with black navigationBar (this was reported as a bug also, don't now if it's
fixed already).
You know how to add an event to calendar, so there's no need to write about getting a reference to EKEventStore and EKCalendar.
You're also not asking about how to retreive an event from calendar so let's assume you already have some kind of mechanism to select (receive) the event and you want to edit it. Let's say it is:
EKEvent *selectedEvent = (EKEvent *)[events objectAtIndex: selectedIndex];
I create this viewController as a property of appDelegate - you probably have better solution. appDelegate also holds eventStore and defaultCalendar reference - your approach could differ.
appDelegate.detailViewController = [[MPEventViewController alloc] initWithNibName:nil bundle:nil];
appDelegate.detailViewController.event = selectedEvent;
appDelegate.detailViewController.eventStore = appDelegate.eventStore;
appDelegate.detailViewController.defaultCalendar = appDelegate.defaultCalendar;
appDelegate.detailViewController.allowsEditing = NO;
[appDelegate.navigationController pushViewController:appDelegate.detailViewController animated:YES];
Sublcassing (again, this is not neccessary but it might come useful) goes like this:
MPEventEditViewController.h
#import <Foundation/Foundation.h>
#import <EventKitUI/EventKitUI.h>
#interface MPEventViewController : EKEventViewController <EKEventEditViewDelegate>
#property (nonatomic, strong) EKEventStore *eventStore;
#property (nonatomic, strong) EKCalendar *defaultCalendar;
- (void)editEvent:(id)sender;
#end
MPEventEditViewController.m
#import "MPEventViewController.h"
#import "----------AppDelegate.h"
#implementation MPEventViewController
#synthesize eventStore;
#synthesize defaultCalendar;
- (void)viewDidLoad {
[super viewDidLoad];
[self setTitle: [self.event title]];
self.allowsEditing = NO;
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:
UIBarButtonSystemItemEdit target:self action:#selector(editEvent:)];
//this has nothing to do with the answer :)
//[[self.navigationController navigationBar] setTintColor: [UIColor colorWithHexString: NAVBAR_TINT_COLOR]];
}
- (void)editEvent:(id)sender {
EKEventEditViewController *addController = [[EKEventEditViewController alloc] initWithNibName:nil bundle:nil];
//this has nothing to do with the answer :)
//[addController.navigationBar setTintColor: [UIColor colorWithHexString: NAVBAR_TINT_COLOR]];
addController.eventStore = self.eventStore;
addController.event = self.event;
addController.navigationBar.barStyle = UIBarStyleBlack;
addController.editViewDelegate = self;
[self presentModalViewController:addController animated:YES];
}
- (void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action {
NSError *error = nil;
EKEvent *thisEvent = controller.event;
switch (action) {
case EKEventEditViewActionCanceled:
break;
case EKEventEditViewActionSaved:
[controller.eventStore saveEvent:controller.event span: EKSpanFutureEvents error:&error];
break;
case EKEventEditViewActionDeleted:
[controller.eventStore removeEvent:thisEvent span: EKSpanFutureEvents error:&error];
break;
default:
break;
}
//here would be the place to reload data if you hold it in some kind of UITableView
[controller dismissModalViewControllerAnimated:YES];
}
- (EKCalendar *)eventEditViewControllerDefaultCalendarForNewEvents:(EKEventEditViewController *)controller {
EKCalendar *calendarForEdit = self.defaultCalendar;
return calendarForEdit;
}
- (void)dealloc {
eventStore = nil;
defaultCalendar = nil;
}
#end
Only after writing all this i remembered there is a great sample code SimpleEKDemo. In fact some of this posted code is probably originates from there.
EDIT:
After the question was edited the above answer became off-topic.
In that case you should take a look at EKCalendarItem and EKevent.
You can change allmost all properties programatically (most of them are inherited from EKCalendarItem).
Maybe you were distracted for example becaues hasNotes is readonly. That is because hasNotes is kind of a function and not a real property. Properties like notes, atendees, startDate, endDate etc. are perfectly editable.
For saving modified event you can still use:
NSError error = nil;
[self.eventStore saveEvent:event span: EKSpanFutureEvents error:&error];
And for deleting it:
NSError error = nil;
[self.eventStore removeEvent:event span: EKSpanFutureEvents error:&error];
EDIT2: for deleting all events try this:
//assuming self.eventStore is already properly set in code
//identifierArray would be your NSMutableArray holding event identifiers
//change the name according to your code
NSError error = nil;
for (NSString *eventIdentifier in removeAllObjects) {
EKEvent *event = [self.eventStore eventWithIdentifier:eventIdentifier];
[self.eventStore removeEvent:event span:EKSpanFutureEvents error:&error];
}
//now you can also clear identifiers
[removeAllObjects removeAllObjects];
Note: there's no guarantee you'll be able to delete all events - only events from
default calendar which is set by usert in settings app.
does EKEventEditViewController not support being pushed to a NavController? See code & error attached.
I can present the EKEventEditViewController modally fine, BUT when I try to push via the nav controller I get the following error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Pushing a navigation controller is not supported'
Code is:
EKEventEditViewController *addController = [[[EKEventEditViewController alloc] initWithNibName:nil bundle:nil] autorelease];
addController.eventStore = self.eventStore;
addController.editViewDelegate = self;
[self.navigationController pushViewController:addController animated:TRUE]; // ERROR HERE
EKEventEditViewController is subclass of UINavigationController, so it can't be pushed to another UINavigationController.
EKEventEditViewController should be presented modally.
EKEventEditViewController Class Ref
In case you're looking for some code to jumpstart an iPad-with-popover implementation:
EKEventStore *eventStore [[EKEventStore alloc] init];
EKEventEditViewController *eventController = [[EKEventEditViewController alloc] init];
eventController.editViewDelegate = self;
eventController.eventStore = eventStore;
EKEvent *event = [EKEvent eventWithEventStore: eventStore];
event.title = #"New Event";
event.startDate = [[NSDate alloc] init];
event.endDate = [[NSDate alloc] initWithTimeInterval: 60 * 60 sinceDate: event.startDate];
eventController.event = event;
/* You can add EKEventEditViewController directly to the popover -- this had me baffled for _hours_ */
popover = [[UIPopoverController alloc] initWithContentViewController: eventController];
You will also want to include this delegate method to do whatever you need to when the user completes or cancels event editing:
- (void) eventEditViewController: (EKEventEditViewController *)controller didCompleteWithAction: (EKEventEditViewAction)action
{
EKEvent *thisEvent = controller.event;
switch (action) {
case EKEventEditViewActionCanceled:
NSLog(#"Canceled action");
break;
case EKEventEditViewActionSaved:
NSLog(#"Saved action: %#", thisEvent.startDate);
break;
case EKEventEditViewActionDeleted:
NSLog(#"Deleted action");
break;
default:
break;
}
[popover dismissPopoverAnimated: YES];
}
Enjoy!
Mark
For future readers:
EKEventEditViewController is a UINavigationController so you can just say:
EKEventEditViewController *controller = [[EKEventEditViewController alloc] init];
// Set your properties here
[self.navigationController pushViewController:controller.viewControllers[0] animated:YES];
This works for me, but I don't know if you can do this for Apple.