So I present an EKEventViewController with a UINavigationController. From inside the EKEventViewController I am able to edit the event. It presents an EKEventEditViewController. Everything thing works great(cancel/done buttons) except when I delete the event inside the EKEventEditViewController I recieve this
attempt to dismiss modal view controller whose view does not currently appear. self = modalViewController =
Here is my code...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[CalendarViewController connectExchange];
if (connectionEx == YES)
{
NSDate *dateRepresentingThisDay = [self.sortedDays objectAtIndex:indexPath.section];
NSArray *eventsOnThisDay = [self.sections objectForKey:dateRepresentingThisDay];
EKEventViewController *eventViewController = [[EKEventViewController alloc] init];
eventViewController.allowsEditing = YES;
eventViewController.delegate = self;
EKEvent *event = [eventsOnThisDay objectAtIndex:indexPath.row];
eventViewController.event = event;
UINavigationController *navBar = [[UINavigationController alloc]initWithRootViewController:eventViewController];
[self.navigationController presentViewController:navBar animated:YES completion:nil];
}
}
- (void)eventViewController:(EKEventViewController *)controller didCompleteWithAction:(EKEventViewAction)action
{
EKEvent *event = controller.event;
CalendarViewController * __weak weakSelf = self;
// Dismiss the modal view controller
[self dismissViewControllerAnimated:YES completion:^
{
if (action == EKEventViewActionDone)
{
dispatch_async(dispatch_get_main_queue(), ^{
NSError *err;
[self.eventStore saveEvent:event span:EKSpanThisEvent error:&err];
[self updateEvent:event];
});
}
if (action == EKEventViewActionDeleted)
{
dispatch_async(dispatch_get_main_queue(), ^{
[self deleteEvent:event];
NSError *error;
EKEvent *eventRemove = [self.eventStore eventWithIdentifier:event.eventIdentifier];
[self.eventStore removeEvent:eventRemove span:EKSpanThisEvent error:&error];
});
}
if (action == EKEventViewActionResponded)
{
dispatch_async(dispatch_get_main_queue(), ^{
});
}
weakSelf.eventsList = [self fetchEvents];
[weakSelf.tableView reloadData];
NSLog(#"Event Updated");
}];
}
How am I suppose to properly dismiss the ViewControllers after deleting the event via the EKEventEditViewController?
I solved my problem by subclassing EKEventViewController and setting up EKEventEditViewDelegate and EKEventViewDelegate.
Here is my changed didSelectRow(CalendarViewController.m),
EditViewController *eventViewController = [[EditViewController alloc] init];
eventViewController.allowsEditing = YES;
eventViewController.delegate = self;
EKEvent *event = [eventsOnThisDay objectAtIndex:indexPath.row];
eventViewController.event = event;
[self.navigationController pushViewController:eventViewController animated:YES];
self.editingEvent = eventViewController.event;
The EditViewController is my subclass of EKEventViewController.
In the subclass(EditViewController.m) I added my own edit button with a selector in viewDidLoad,
- (void)viewDidLoad
{
[super viewDidLoad];
UIBarButtonItem *editItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self.delegate action:#selector(editCalEvent)];
self.navigationItem.rightBarButtonItem = editItem;
}
Now back in CalendarViewController.m after adding the EKEventEditViewDelegate and EKEventViewDelegate to the #interface I added new methods
- (void)editCalEvent
{
EKEventEditViewController *editController = [[EKEventEditViewController alloc] init];
editController.event = self.editingEvent;
editController.eventStore = self.eventStore;
editController.editViewDelegate = self;
[self presentViewController:editController animated:YES completion:nil];
}
- (void)eventEditViewController:(EKEventEditViewController *)controller didCompleteWithAction (EKEventEditViewAction)action
{
EKEvent *thisEvent = controller.event;
[self dismissViewControllerAnimated:NO completion:^
{
switch (action)
{
{case EKEventEditViewActionCanceled:
//NSLog(#"Canceled action");
break;}
{case EKEventEditViewActionSaved:
[self.eventStore saveEvent:thisEvent span:EKSpanThisEvent error:nil];
[self updateEvent:thisEvent];
break;}
{case EKEventEditViewActionDeleted:
[self deleteEvent:thisEvent];
NSError *error;
EKEvent *eventRemove = [self.eventStore eventWithIdentifier:thisEvent.eventIdentifier];
[self.eventStore removeEvent:eventRemove span:EKSpanThisEvent error:&error];
//NSLog(#"Deleted action");
break;}
{default:
break;}
}
}];
}
- (void)eventViewController:(EKEventViewController *)controller didCompleteWithAction:(EKEventViewAction)action
{
}
Use the editViewDelegate instead of delegate.
Related
I am working on a iOS Application in which I have to add contacts in Address Book.
I want to open Edit Contact Screen Whenever user Tries to add duplicate contact.
But I don't know how to do that.Currently I am only able to show a message only.
I am getting all contacts list as:
NSArray *allContacts = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBookRef);
Then I am itterating through it and check for existing one.If it exists then I am showing a message else I will add it to the addressbook.
for (id record in allContacts){
ABRecordRef thisContact = (__bridge ABRecordRef)record;
if (CFStringCompare(ABRecordCopyCompositeName(thisContact),
ABRecordCopyCompositeName(pet), 0) == kCFCompareEqualTo){
//The contact already exists!
NSLog(#"contact exosts");
}
else
{
ABAddressBookAddRecord(addressBookRef, pet, nil);
ABAddressBookSave(addressBookRef, nil);
ABMultiValueAddValueAndLabel(phoneNumbers, (__bridge CFStringRef)petPhoneNumber, kABPersonPhoneMainLabel, NULL);
NSLog(#"contacts Added");
}
}
How can I open following screen when user Tries to add duplicate contact:
I searched SO and find following questions but this doesn't help me.
Question 1
Question 2
And Is it possible to do so or not.Please any one assist me to achieve this feature if it is feasible.
See here .h
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#interface ContactsViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, ABPersonViewControllerDelegate>
{
IBOutlet UITableView *tblContacts;
NSMutableArray *arrContacts;
}
#end
And .m
#import "ContactsViewController.h"
#interface ContactsViewController ()
{
UIAlertController *action;
}
#end
#implementation ContactsViewController
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Contacts";
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addNewContact:)];
[self getContactsUsingAddressbook];
}
#pragma mark - Methods
// ------- Deprecated (in iOS 9.0) ----------
- (void)getContactsUsingAddressbook
{
ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();
if (status == kABAuthorizationStatusDenied || status == kABAuthorizationStatusRestricted)
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:#"This app previously was refused permissions to contacts; Please go to settings and grant permission to this app so it can use contacts" preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alert animated:TRUE completion:nil];
return;
}
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (!addressBook)
{
NSLog(#"ABAddressBookCreateWithOptions error: %#", CFBridgingRelease(error));
return;
}
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
if (error)
{
NSLog(#"ABAddressBookRequestAccessWithCompletion error: %#", CFBridgingRelease(error));
}
if (granted)
{
NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
arrContacts = [NSMutableArray arrayWithArray:allPeople];
[tblContacts reloadData];
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
[[[UIAlertView alloc] initWithTitle:nil message:#"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
});
}
CFRelease(addressBook);
});
}
#pragma mark - Tableview delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return arrContacts.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
//if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
cell.accessoryType = UITableViewCellAccessoryDetailButton;
// ------- Deprecated (in iOS 9.0) ----------
ABRecordRef person = (__bridge ABRecordRef)arrContacts[indexPath.row];
NSString *firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", firstName, lastName];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// ------- Deprecated (in iOS 9.0) ----------
ABPersonViewController *personController = [[ABPersonViewController alloc] init];
personController.personViewDelegate = self;
personController.displayedPerson = (__bridge ABRecordRef)arrContacts[indexPath.row];
personController.allowsEditing = YES;
personController.allowsActions = YES;
[self.navigationController pushViewController:personController animated:TRUE];
}
#pragma mark - ABPersonview delegate
- (BOOL)personViewController:(ABPersonViewController *)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
{
return TRUE;
}
And see in my simulator
You can edit contact as following
Here you have to add
// ------- Deprecated (in iOS 9.0)
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
ABPersonViewController *personController = [[ABPersonViewController alloc] init];
personController.personViewDelegate = self;
personController.displayedPerson = (__bridge ABRecordRef)arrContacts[indexPath.row];
personController.allowsEditing = YES;
personController.allowsActions = YES;
[self.navigationController pushViewController:personController animated:TRUE];
And here
#import <Contacts/Contacts.h>
#import <ContactsUI/ContactsUI.h>
// -------- This is not working for me, I got error
CNContact *contact = [arrContacts objectAtIndex:indexPath.row];
NSArray *keys = #[CNContactIdentifierKey, CNContactEmailAddressesKey, CNContactBirthdayKey, CNContactImageDataKey, CNContactPhoneNumbersKey, [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]];
CNContactViewController *contactController = [CNContactViewController viewControllerForContact:contact];
contactController.delegate = self;
contactController.allowsEditing = YES;
contactController.allowsActions = YES;
contactController.displayedPropertyKeys = keys;
[self.navigationController pushViewController:contactController animated:TRUE];
See here Contact is missing some of the required key descriptors in ios
But still I have not found solution , If you have please tell me
Here is the answer
when bind arrayOfContact That time have to Provide key with [CNContactViewController descriptorForRequiredKeys].
NSArray *keys = #[CNContactGivenNameKey,CNContactFamilyNameKey,CNContactOrganizationNameKey, CNContactPhoneNumbersKey, CNContactEmailAddressesKey,CNContactPostalAddressesKey,[CNContactViewController descriptorForRequiredKeys]]
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
when open existing Contact
CNContactViewController *contactController = [CNContactViewController viewControllerForContact:contact];
contactController.delegate = self;
contactController.allowsEditing = YES;
contactController.allowsActions = YES;
[self.navigationController pushViewController:contactController animated:TRUE];
I'm having a heck of a time figuring this out.
I have a modal view that appears when tapping on one of the tabs of a tab bar. In the new view that takes over the whole screen, there is a button a user taps to start recording audio, and when they're finished recording audio, or if they cancel recording, the modal view is dismissed.
The problem is that, once they start recording, that red recording bar should appear on this new view. But it's not. And as soon as that view is dismissed, in the next view that is presented (a table view, which is found in one of the tabs), you can see the red recording bar at the top for a split second and it disappears BUT it shoves the tab bar down the screen and obscures part of the tab bar, which you can see in the third screenshot below.
Modal view pops up - recording is currently in progress, but red recording indicator is not showing at the top
Right when the recording is done and the view is about to disappear, the red bar appears
And once the view disappears and we're left with the table view that lives in one of the tabs, the tab bar is shoved down past the bottom of the screen :( It SHOULD look like this (with the fourth tab selected):
My questions:
1) What am I doing wrong that's causing the red recording bar to NOT show up in the modal view?
2) Is there a way to maybe refresh this view from the screenshot so that when it appears, it resizes properly?
Here's the code. I removed some of the non-important stuff that doesn't deal with the views.
#interface AudioViewController ()
#end
#implementation AudioViewController
#synthesize fileData;
UILabel *countdownLabel;
- (void)viewDidLoad
{
[super viewDidLoad];
self.friendsRelation = [[PFUser currentUser] objectForKey:#"friendsRelation"];
self.recipients = [[NSMutableArray alloc] init];
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.audioPicker = [[UIViewController alloc] init];
self.audioPicker.view.backgroundColor = [UIColor yellowColor];
self.friendsRelation = [[PFUser currentUser] objectForKey:#"friendsRelation"];
PFQuery *query = [self.friendsRelation query];
[query orderByAscending:#"username"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error %# %#", error, [error userInfo]);
}
else {
self.friends = objects;
[self.tableView reloadData];
}
}];
UIButton *cancelBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
cancelBtn.frame = CGRectMake(50.0, 200.0, 200.0, 200.0);
cancelBtn.titleLabel.font = [UIFont systemFontOfSize:20];
[cancelBtn setTitle:#"Cancel" forState:UIControlStateNormal];
[self.audioPicker.view addSubview:cancelBtn];
cancelBtn.center = CGPointMake(self.view.center.x, 400);
[cancelBtn addTarget:self action:#selector(exitRecordingScreen) forControlEvents:UIControlEventTouchUpInside];
UIButton *recordBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
recordBtn.frame = CGRectMake(50.0, 50.0, 200.0, 200.0);
recordBtn.titleLabel.font = [UIFont systemFontOfSize:50];
[recordBtn setTitle:#"Record" forState:UIControlStateNormal];
recordBtn.center = CGPointMake(self.view.center.x, 100);
[self.audioPicker.view addSubview:recordBtn];
if ([self respondsToSelector:#selector(timeout)]) {
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timeout) userInfo:nil repeats:NO];
} else {
NSLog(#"Error: missing selector");
}
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayAndRecord
withOptions:AVAudioSessionCategoryOptionDuckOthers
error:nil];
if (!fileData) {
[self presentViewController:self.audioPicker animated:NO completion:nil];
NSLog(#"File data: %#", fileData);
[recordBtn addTarget:self action:#selector(startRecordingAudio) forControlEvents:UIControlEventTouchUpInside];
} else {
NSLog(#"Existing File data: %#", fileData);
}
}
- (void) timeout {
[self.navigationController popViewControllerAnimated:YES];
}
# pragma mark - Audio Recording Methods
////////
// Removed some stuff here that is not manipulating views
////////
- (void) stopRecordingOnAudioRecorder:(AVAudioRecorder *)paramRecorder{
/* Just stop the audio recorder here */
[paramRecorder stop];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder
successfully:(BOOL)flag{
if (flag) {
NSLog(#"Stopped recording process");
NSError *playbackError = nil;
NSError *readingError = nil;
fileData = [NSData dataWithContentsOfURL:[self audioRecordingPath]
options:NSDataReadingMapped
error:&readingError];
self.audioPlayer = [[AVAudioPlayer alloc] initWithData:fileData
error:&playbackError];
if (self.audioPlayer != nil) {
self.audioPlayer.delegate = self;
//Prepare and start playing
if ([self.audioPlayer prepareToPlay] && [self.audioPlayer play]) {
NSLog(#"Started playing recorded audio");
} else {
NSLog(#"Couldn't play recorded audio");
}
} else {
NSLog(#"Failed to create audio player");
}
} else {
NSLog(#"Stopping audio recording failed");
}
self.audioRecorder = nil;
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player
successfully:(BOOL)flag{
if (flag){
NSLog(#"Audio player stopped correctly.");
} else {
NSLog(#"Audio player did not stop correctly.");
}
if ([player isEqual:self.audioPlayer]){
self.audioPlayer = nil;
} else {
/* This is not the player */
}
}
# pragma mark - TableView methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.friends count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFUser *user = [self.friends objectAtIndex:indexPath.row];
cell.textLabel.text = user.username;
// makes sure checkmark isn't reused if user didn't explicitly select name
if ([self.recipients containsObject:user.objectId]) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)reset {
self.audioFile = nil;
}
// User hits "Cancel" button
-(void)exitRecordingScreen {
[self reset];
[self.presentedViewController dismissViewControllerAnimated:NO completion:nil];
[self.tabBarController setSelectedIndex:0];
NSLog(#"exit recording screen button pressed");
}
- (IBAction)send:(id)sender {
if (self.audioFile == nil) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Please try again." message:#"Please record audio again to share." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[self presentViewController:self.audioPicker animated:NO completion:nil];
} else {
[self uploadMessage];
[self.tabBarController setSelectedIndex:0];
}
}
// Cancel sending recorded file
- (void)cancel:(id)sender {
fileData = nil;
[self reset];
[self.tabBarController setSelectedIndex:0];
}
#end
Sorry for the wall of text and the length. I'm really stumped.
Solution : You have to reset frame for UITabBarController.
1. Initially frame for UITabBarController will be (0,0,screenWidth,screenHeight).
2. But when this recording red bar appear it becomes (0,20,screenWidth,screenHeight)
3. Here you are supposed to change height for UITabBarController
CGRect changedFrame = objMainTabBarController.view.frame;
changedFrame.size.height = [UIScreen mainScreen].bounds.size.height - CGRectGetMinY(changedFrame);
objMainTabBarController.view.frame = changedFrame;
That's it..
I've developed an App and my App needs to create an event at device's calendar. I've been trough EventKitProgGuide and studied the SimpleEKDemo.
By simplifying the code from SimpleEKDemo I generated the code shown below that opens an 'calendar's event screen' straight from my app and generates the event properly. I'm OK with that.
Now I need to use the text content of an UITextView as the Event Title!
Could somebody help my with that code?
Thanks,
Marcos
Here's my code:
#.h
#import <EventKitUI/EventKitUI.h>
#import <EventKit/EventKit.h>
#property (nonatomic, strong) EKEventStore *eventStore;
#property (nonatomic, strong) EKEvent *event;
#property (nonatomic, strong) EKCalendar *defaultCalendar;
#property (nonatomic, strong)
IBOutlet UITextView *textView1;
- (IBAction)agendar:(UIButton *)sender;
#.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.eventStore = [[EKEventStore alloc]init];
self.textView1.text = #"hello world!";
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self checkEventStoreAccessForCalendar];
}
- (IBAction)agendar:(UIButton *)sender {
EKEventEditViewController *addController = [[EKEventEditViewController alloc] init];
addController.eventStore = self.eventStore;
addController.editViewDelegate = self;
[self presentViewController:addController animated:YES completion:nil];
self.event = [EKEvent eventWithEventStore:self.eventStore];
// Jeff's suggested code:
self.event.title = self.textView1.text;
// Jeff's SaveEvent Sugestion
NSError *err;
[self.eventStore saveEvent:self.event span:EKSpanThisEvent error:&err];
}
-(void)checkEventStoreAccessForCalendar
{
EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
switch (status)
{
case EKAuthorizationStatusAuthorized: [self accessGrantedForCalendar];
break;
case EKAuthorizationStatusNotDetermined: [self requestCalendarAccess];
break;
case EKAuthorizationStatusDenied:
case EKAuthorizationStatusRestricted:
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alerta de Privacidade" message:#"Permissão de acesso ao calendário não concedida."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
break;
default:
break;
}
}
-(void)requestCalendarAccess
{
[self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error)
{
if (granted)
{
Tela8ViewController * weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf accessGrantedForCalendar];
});
}
}];
}
-(void)accessGrantedForCalendar
{
self.defaultCalendar = self.eventStore.defaultCalendarForNewEvents;
}
- (void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action
{
[self dismissViewControllerAnimated:YES completion:^
{
if (action != EKEventEditViewActionCanceled)
{
dispatch_async(dispatch_get_main_queue(), ^{
});
}
}];
}
There are two ways to create an event with EventKit. Your sample code currently has a mix of both, so you should pick just one!
A: Create an event with certain fields pre-set (in your case, the title), and allow the user to review and save it (or choose to cancel and discard it) with EKEventEditViewController. In this case, your code doesn't need to commit the event - just watch for the delegate response to confirm that it happened.
- (void)createEventWithTitle:(NSString *)title
{
EKEvent *newEvent = [EKEvent eventWithEventStore:self.eventStore];
newEvent.title = title;
EKEventEditViewController *controller = [[EKEventEditViewController alloc] init];
controller.eventStore = self.eventStore;
controller.event = newEvent;
controller.editViewDelegate = self;
[self presentViewController:controller animated:YES completion:nil];
}
// EKEventEditViewController delegate method
- (void)eventEditViewController:(EKEventEditViewController *)controller didCompleteWithAction:(EKEventEditViewAction)action
{
if (action == EKEventEditViewActionSaved) {
// event has been committed
}
// alternatives are EKEventEditViewActionCanceled, EKEventEditViewActionDeleted
[self dismissViewControllerAnimated:YES completion:Nil];
}
B. You can create an event and commit it entirely in your code, if you don't need user involvement. In this case you can use EKEventStore saveEvent: span: error: instead of relying on EKEventEditViewController.
Have you tried something like
self.event.title = self.textView1.text;
?
I am having a screen for adding a reminder. The screen is having 2 textfields and 1 textview. These all are under scrollView which is a subclass of TPAvoidingScrollView class. This class itself manages the position of scrollView and hence the components inside as the keyboard appears and disappears.
The screen is as follows.
After I have gone through all the fields and selected certain values. By clicking on Add reminder the event is added into the main calendar and the screen pops out to the previous screen. And then problem starts to occur. As soon as I again comes to this screen and tapping on the Textview Notes the app crashes with these errors.
Here Reminder view controller is the name of the class
The code for the whole class is:
#import "ReminderViewController.h"
#import <EventKit/EventKit.h>
#import "ActionSheetPicker.h"
#import "NSDate-Utilities.h"
#interface ReminderViewController ()
#end
#implementation ReminderViewController
#synthesize scrollView;
#synthesize txt_notes;
#synthesize txt_remindOn;
#synthesize txt_repeatAlarm;
#synthesize btn_appointment;
#synthesize btn_pickup;
#synthesize btn_reminder;
#synthesize txt_currentFocussedTextField;
#synthesize selectedDate;
#synthesize arr_repeatAlarm;
#synthesize selectedIndex;
#synthesize isSelected;
#synthesize str_eventTitle;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.scrollView.contentSize = CGSizeMake(320, 520);
self.selectedDate = [NSDate date];
self.arr_repeatAlarm = [NSArray arrayWithObjects:#"None",#"Every Day", #"Every Week",
#"Every Month", #"Every year", nil];
btn_reminder.backgroundColor =[UIColor colorWithRed:0.0/255 green:89.0/255 blue:178.0/255
alpha:1.0f];
[[AppDelegate sharedInstance] setUpHighlightedStateOfButton:btn_reminder];
// Do any additional setup after loading the view.
}
#pragma mark - Check button click methods
-(IBAction)btn_appointment_click:(id)sender{
if(btn_appointment.selected){
[btn_appointment setSelected:NO];
[btn_pickup setSelected:YES];
isSelected = NO;
}
else{
[btn_appointment setSelected:YES];
[btn_pickup setSelected:NO];
isSelected = YES;
}
}
-(IBAction)btn_pickup_click:(id)sender{
if(btn_pickup.selected){
[btn_pickup setSelected:NO];
[btn_appointment setSelected:YES];
isSelected = NO;
}
else{
[btn_pickup setSelected:YES];
[btn_appointment setSelected:NO];
isSelected = YES;
}
}
#pragma mark - calendar Event methods
- (IBAction)btn_reminder_click:(id)sender{
[self addEventTocalendar:sender];
}
- (void)addEventTocalendar:(id)sender{
EKEventStore *store = [[EKEventStore alloc] init];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError
*error) {
if (!granted) { return; }
EKEvent *event = [EKEvent eventWithEventStore:store];
event.title = #"Pickup Reminder";
event.startDate = self.selectedDate;
event.endDate = [event.startDate dateByAddingTimeInterval:60*60];//set 1 hour meeting
event.notes = txt_notes.text;
event.recurrenceRules = EKRecurrenceFrequencyDaily;
[event addAlarm:[EKAlarm alarmWithRelativeOffset:60.0f * -5.0f]];
if (selectedIndex == 1) {
[event addRecurrenceRule:[[EKRecurrenceRule
alloc]initRecurrenceWithFrequency:EKRecurrenceFrequencyDaily interval:1 end:Nil]];
}
else if (selectedIndex == 2){
[event addRecurrenceRule:[[EKRecurrenceRule
alloc]initRecurrenceWithFrequency:EKRecurrenceFrequencyWeekly interval:1 end:Nil]];
}
else if (selectedIndex == 3){
[event addRecurrenceRule:[[EKRecurrenceRule
alloc]initRecurrenceWithFrequency:EKRecurrenceFrequencyMonthly interval:1 end:Nil]];
}
else if (selectedIndex == 4){
[event addRecurrenceRule:[[EKRecurrenceRule
alloc]initRecurrenceWithFrequency:EKRecurrenceFrequencyYearly interval:1 end:Nil]];
}
[event setCalendar:[store defaultCalendarForNewEvents]];
NSError *err = nil;
[store saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
NSString *savedEventId = event.eventIdentifier; //this is so you can access this
event later
BOOL isSuceess=[store saveEvent:event span:EKSpanThisEvent error:&err];
// This needs to be done as the UIKIT was getting called from the seconadary thread
and therefore to show the alert view in the main thread and to prevent the hanging of
the app I have to call the Aletview method in the main thread.
// i.e dispatch the event in the main thread
if(isSuceess){
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:#"Event"
message:#"Event added in calendar" delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[alertview show];
});
}
else {
UIAlertView *alertview = [[UIAlertView alloc] initWithTitle:#"Event" message:[err
description] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[alertview show];
});
}
}];
}
- (void)back{
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - UIAlertViewDelegate methods
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - Implementation methods
- (void)serviceWasSelected:(NSNumber *)selectedIndex element:(id)element {
self.selectedIndex = [selectedIndex intValue];
//may have originated from textField or barButtonItem, use an IBOutlet instead of element
self.txt_repeatAlarm.text = [self.arr_repeatAlarm objectAtIndex:self.selectedIndex];
}
- (void)dateWasSelected:(NSDate *)selectedDate element:(id)element{ //indexpath:
(NSIndexPath *)indexpath{
UITextField * textfield = (UITextField *)element;
if (textfield == self.txt_remindOn) {
self.selectedDate = selectedDate;
self.txt_remindOn.text = [self.selectedDate getDateStringInFormat:#"dd MMM yyyy
hh:mm aa"];
}
}
#pragma mark - TextField Delegate Methods
- (void)textFieldDidBeginEditing:(UITextField *)textField{
self.txt_currentFocussedTextField = textField;
[[AppDelegate sharedInstance] addToolbarForKeyboard:textField];
if (textField == self.txt_remindOn) {
[textField resignFirstResponder];
_actionSheetPicker = [[ActionSheetDatePicker alloc] initWithTitle:#""
datePickerMode:UIDatePickerModeDateAndTime selectedDate:self.selectedDate
minimumDate:[NSDate
date] maximumDate:Nil target:self action:#selector(dateWasSelected:element:)
origin:textField];
self.actionSheetPicker.hideCancel = NO;
[self.actionSheetPicker showActionSheetPicker];
}
if (textField == self.txt_repeatAlarm) {
[textField resignFirstResponder];
[ActionSheetStringPicker showPickerWithTitle:#"" rows:self.arr_repeatAlarm
initialSelection:self.selectedIndex target:self
successAction:#selector(serviceWasSelected:element:)
cancelAction:#selector(actionPickerCancelled:) origin:textField];
}
}
// making the keyboard disappear on pressing the Done button on the keyboard.
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return NO;
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text {
if([text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
This is my first post because I usually find all the answers on stack overflow but not this time !
I have a little problem.
I am using the following methods :
-(void)scrollToTop;
{
[_scrollView setContentOffset:CGPointZero animated:YES];
}
sometimes it animates sometimes not !
This one works :
-(void)newPage:(NSString*)href
{
if(!(_pageNumber == href.integerValue))
{
__weak id weakSelf = self;
[(PageViewController*)_preLoadPages[href] setPageMinHeight:_actualPage.height];
NSMutableArray *viewControllers = [[NSMutableArray alloc] init];
viewControllers[0] = _preLoadPages[href];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished){
[weakSelf afterLinkClicked:href];
}];
_pageNumber = href.integerValue;
}
}
- (void)afterLinkClicked:(NSString*)href
{
_pageNumber = href.integerValue;
[_preLoadPages[href] setPageMinHeight:0];
_actualPage = _preLoadPages[href];
[_preLoadPages removeAllObjects];
[self updateScrollView];
[self scrollToTop];
[self parsePage];
}
Whereas this one does not :
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
CGPoint test = [gestureRecognizer locationInView:gestureRecognizer.view];
if(test.x>=742)
{
if(_preLoadPages[#"next"]!=nil)
{
__weak id weakSelf = self;
[(PageViewController*)_preLoadPages[#"next"] setPageMinHeight:_actualPage.height];
NSMutableArray *viewControllers = [[NSMutableArray alloc] init];
viewControllers[0] = _preLoadPages[#"next"];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished){
[weakSelf afterAnimationCompleted];
}];
}
}
return YES;
}
- (void)afterAnimationCompleted
{
_pageNumber++;
[_preLoadPages[#"next"] setPageMinHeight:0];
_actualPage = _preLoadPages[#"next"];
[_preLoadPages removeAllObjects];
[self updateScrollView];
[self scrollToTop];
[self parsePage];
}
There is practically no differences between these two calls !
I have tried to use performSelector: withObject: withDelay:0 but it doesn't work too !!