Highlight UITableViewCell while pickerview event - objective-c

I have a UI which contains a UITableView and a UIDatePicker. When I select a Row on my table it is highlighted, but as soon as I interact with the DatePicker (scroll to a new value) the row isn't highlighted anymore. The value of the row is bound to that of the DatePicker. How can I permanently highlight the cell?
In the iCal-App -> Add -> Start&End I saw this behaviour.
I tried the selectRowAtIndex method in my ValueChanged-method of the picker. I thought that the highlighting is lost in this callback-method.
-(IBAction)setStartTimeMethod
{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"EEE, dd. MMM yyyy HH:mm"];
if(!self.endDateRowSelected)
self.date = [dateFormat stringFromDate:[datePicker date]];
else
self.endDate = [dateFormat stringFromDate:[datePicker date]];
[dateFormat release];
// [self.tableView1 selectRowAtIndexPath:tableView1.indexPathForSelectedRow animated:NO scrollPosition:UITableViewScrollPositionTop];
[self.tableView1 reloadData];
}
Edit, my didSelectRowMethod
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"EEE, dd. MMM yyyy HH:mm"];
if(indexPath.row == 0){
NSLog(#"Start");
self.endDateRowSelected = NO;
NSDate *startDate = [formatter dateFromString:self.date];
[datePicker setDate:startDate animated:YES];
//if(self.endDateRowSelected)
// [tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
}else if(indexPath.row == 2){
NSLog(#"End");
self.endDateRowSelected = YES;
if(self.endDate){
NSDate *endDateTime = [formatter dateFromString:self.endDate];
[datePicker setDate:endDateTime animated:YES];
}
}else{
self.endDateRowSelected = NO;
}
[formatter release];
// Won't work, doesn't allow highlighting a cell.
// [tableView deselectRowAtIndexPath:indexPath animated:NO];
}
BR,
mybecks

Use this piece of code in the end of didSelectRowAtIndexPath delegate method of table view,
[tableView deselectRowAtIndexPath:indexPath animated:NO];

Try:
[self.tableView1 reloadData];
// and then
[self.tableView1 selectRowAtIndexPath:tableView1.indexPathForSelectedRow animated:NO scrollPosition:UITableViewScrollPositionTop];
I guess a much better way of doing this is with IBOutlets for each custom cell in your table. If you are editing the date for that cell, then why reload the entire table? If you have less number of cells, you can go ahead and create custom UITableViewCell, add labels and update only those labels from your UIDatePicker delegate callbacks.

Use the following code in didSelectRowAtIndexPath
cell.selectionStyle=UITableViewCellSelectionStyleBlue;

The solution was quite easy.
In my cellForRowAtIndexPath I must call the selectRowAtIndexPath method.
...
if(indexPath.row == 0){
cell.description.text = [dict objectAtIndex:indexPath.row];
cell.dateTime.text = self.startDate;
if(!endDateRowSelected)
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}else if(indexPath.row == 2){
cell.description.text = [dict objectAtIndex:indexPath.row];
cell.dateTime.text = self.endDate;
if(endDateRowSelected)
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
}
...
The bool is set in my didSelectRowAtIndexPath, depending on clicking on Start or End.
I still reload the table in my pickerValueChanged delegate.
Thank you for time & help.

Related

UIAlertView button is disabled even after picking date from UIDatePicker

The problem is that after picking date from UIDatePicker the "Ok" button of UIAlertView is disabled.I tried ,but no luck.
-(BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
should be called whenever we type anything in textfield,but when date is entered it's not getting called,but if i type anything from keyboard,its ok then.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section == 0 && indexPath.row == 1)
{
alertView1 = [[UIAlertView alloc] initWithTitle:nil message:nil delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Done",nil];
alertView1.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
alertView1.tag=1;
alertText = [alertView1 textFieldAtIndex:0];
itemText = [alertView1 textFieldAtIndex:1];
alertText.inputView=datePicker;
itemText.inputView=secondPicker;
[datePicker addTarget:self action:#selector(firstTF) forControlEvents:UIControlEventValueChanged];
[secondPicker addTarget:self action:#selector(secondTF) forControlEvents:UIControlEventValueChanged];
[alertText setPlaceholder:#"From Date"];
[itemText setPlaceholder:#"To Date"];
itemText.secureTextEntry = NO;
[alertView1 show];
}
- (void)firstTF
{
NSDate *date = datePicker.date;
NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
[dateFormat setDateStyle:NSDateFormatterMediumStyle];
alertText.text = [dateFormat stringFromDate:date];
}
- (void)secondTF
{
NSDate *date = secondPicker.date;
NSDateFormatter *dateFormat = [[NSDateFormatter alloc]init];
[dateFormat setDateStyle:NSDateFormatterMediumStyle];
itemText.text = [dateFormat stringFromDate:date];
}
- (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView
{
NSString *inputText = [[alertView textFieldAtIndex:0] text];
if( [inputText length] > 0)
{
NSLog(#"alertViewShouldEnableFirstOtherButton: was called!");
return YES;
}
else
{
return NO;
}
}
This happens because of "alertViewShouldEnableFirstOtherButton" called before you enter the text in to text field. As per your condition in side the method "Done" button will be disable. Remove this method and you will achieve your target.

Realtime Values in UITableViewCell from UIDatePicker

I have a UIViewController with two UI Components: UITableView and UIDatePicker. My goal is, to create a screen like the ical->add->Start & End.
I added the the tableView delegate and dateSource to my header file. In the implementation file, I want to display the current value from the datePicker in my tableCell (like the iCal Start & End screen).
My .m looks like the following:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[datePicker addTarget:self action:#selector(datePickerValueChanged) forControlEvents:UIControlEventValueChanged];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSMutableArray *dict = [dictionary objectForKey:#"DATA"];
if(indexPath.row == 1){
UISwitch *switchSpecifyEnd = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease];
cell.accessoryView = switchSpecifyEnd;
[(UISwitch *)cell.accessoryView setOn:NO]; // Or NO, obviously!
[(UISwitch *)cell.accessoryView addTarget:self action:#selector(switchSpecifyEnd)
forControlEvents:UIControlEventValueChanged];
cell.textLabel.text = [dict objectAtIndex:indexPath.row];
}else if(indexPath.row == 3){
UISwitch *switchOpenEnd = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease];
cell.accessoryView = switchOpenEnd;
[(UISwitch *)cell.accessoryView setOn:NO]; // Or NO, obviously!
[(UISwitch *)cell.accessoryView addTarget:self action:#selector(switchOpenEnd)
forControlEvents:UIControlEventValueChanged];
cell.textLabel.text = [dict objectAtIndex:indexPath.row];
}else{
cell.textLabel.text = [dict objectAtIndex:indexPath.row];
// NSLog(#"Update Cell: %#",<but how>);
}
return cell;
}
- (void)datePickerValueChanged{
NSLog(#"Logging: %#", [NSString stringWithFormat:#"%#",datePicker.date]);
}
How can I update my tableCell with the value from the datePicker?
BR,
mybecks
For updating your table cell you need to reload your table and when your table will reload then cellForRowAtIndexPath will get call and you can update your cell text.
Suppose this is your method that gets called when you select some date in date picker
-(IBAction)setStartTimeMethod
{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"EEE MMM dd, yyyy hh:mm a"];
self.startTimeString = [dateFormat stringFromDate:[timeStartPicker date]];
[dateFormat release];
[optionsTableView reloadData];
}

How to display events in tableView sorted by NSDate?

I have an events app which gets events data from sqlite database and displays it in tableView. I also converted date from the sqlite table from NSString to NSDate.
Now I want to display records sorted by Date and also don't want to display event that is finished.
Here is my EventViewController.m
#import "EventViewController.h"
#implementation EventViewController
#synthesize events,eDate;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Events";
//Get the DBAccess object;
DBAccess *dbAccess = [[DBAccess alloc] init];
//Get event array from database
self.events = [dbAccess getAllEvents];
//Close the database
[dbAccess closeDatabase];
//Release dbAccess object to free its memory
[dbAccess release];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations.
return YES;
}
#pragma mark -
#pragma mark Table view data source
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(#"# of Sections");
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//NSLog(#"Countring Rows");
return [self.events count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Creating cell");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
event = [self.events objectAtIndex:[indexPath row]];
// Configure the cell.
cell.textLabel.text = event.name;
cell.detailTextLabel.text = event.location;
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//Formate Date from string to NSDate
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyyMMdd"];
NSDate *eeDate = [dateFormatter dateFromString:event.date];
NSLog(#"%#", eeDate);
[dateFormatter setDateFormat:#"EEEE MMMM d, YYYY"];
eDate = [dateFormatter stringFromDate:eeDate];
NSLog(#"%#", eDate);
[dateFormatter release];
//Event *event;
if (tableView == self.tableView)
{
event = [self.events objectAtIndex:[indexPath row]];
//event = [[self.events objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];
}
else
{
event = [self.events objectAtIndex:[indexPath row]];
}
EventDetailViewController *detailViewController = [[EventDetailViewController alloc]
initWithStyle:UITableViewStyleGrouped];
detailViewController.eventDetail = [events objectAtIndex:indexPath.row];
detailViewController.eventName = event.name;
detailViewController.eventLocation = event.location;
detailViewController.eventNote = event.note;
detailViewController.eventDate = eDate;
detailViewController.eventTime = event.time;
//Pust detail controller on to the stack
[self.navigationController pushViewController:(UITableViewController *)detailViewController animated:YES];
//release the view controller
[detailViewController release];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)dealloc
{
[events release];
[super dealloc];
}
#end
Please Help.
Since the date is represented as yyyyMMdd, we can use the usual string comparison to eliminate older events using the current date. Then we can sort the remaining events.
NSArray * allEvents = [dbAccess getAllEvents];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"yyyyMMdd"];
NSString * todaysDateAsString = [dateFormatter stringFromDate:[NSDate date]];
NSArray * futureEvents = [allEvents filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"date >= %#", todaysDateAsString]];
NSSortDescriptor * descriptor = [NSSortDescriptor descriptorWithKey:#"date" ascending:YES];
self.events = [futureEvents sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
You can use NSSortDescriptors to sort your events.
Suppose you have a property finished that indicates when the event is finished, you could filter the array like this
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"finished = NO"];
self.events = [[dbAccess getAllEvents] filteredArrayUsingPredicate:predicate];
And than, if the event object has a date property that is the one you are trying to sort ascending, you could use NSSortDescriptor to sort it.
NSSortDescriptor *descriptor = [NSSortDescriptor alloc] initWithKey:#"date" ascending:YES];
NSArray *arrayDescriptors = [NSArray arrayWithObject: descriptor];
self.events = [self.events sortedArrayUsingDescriptors:arrayDescriptors];
[descriptor release];

Objective C: How to use addTarget:action:forControlEvents: method?

I am trying to update the date and time displayed in a table cell immediately after the UIPicker's data has changed (real time updated). I implemented the following code. My "update" method is not being called despite changing the values in the picker. Can anyone advise? Thanks!
Zhen
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
if (row == 0)
{
self.picker.hidden = NO;
[self.picker addTarget:self action:#selector(updateDate) forControlEvents:UIControlEventTouchUpInside];
}
}
- (void)updateDate
{
selectedDate = [self.picker date];
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"dd-MM-yyyy HH:mm"];
selectedDateString = [formatter stringFromDate:selectedDate];
[tableView reloadData];
}
You need to put a colon after the selector name.
[self.picker addTarget:self action:#selector(updateDate:) forControlEvents:UIControlEventTouchUpInside];
Also, the updateDate method should take an object of type id.
- (void) updateDate:(id) obj { }
change in your code -
[self.picker addTarget:self action:#selector(updateDate:) forControlEvents:UIControlEventTouchUpInside];
to
[self.picker addTarget:self action:#selector(updateDate:) forControlEvents:UIControlEventAllEvents];
you can also handle it in UIPicker delegates.

How can I present a picker view just like the keyboard does?

I want a UIPickerView to show up when I press a button (just like keyboard) and then go away when user taps anywhere on the screen. How can I do this? Thanks.
A bit more background: I have a UITextField called months in UITableViewCell. Now the best option for me is to put a UIPikcerView there and it will be easier for the user to just chose the month rather than having to type it out (and it's the better way). But UIPickerView looks really ugly in a UITableViewCell, not to mention I can't change it's gigantic size. So what should I do in this case?
This is how you should use UIPickerView for a textField in a UITableView.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle= UITableViewCellSelectionStyleNone;
UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(110, 10, 185, 30)];
textField.clearsOnBeginEditing = NO;
textField.textAlignment = UITextAlignmentRight;
textField.delegate = self;
[cell.contentView addSubview:textField];
//textField.returnKeyType = UIReturnKeyDone;
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
// if you want a UIPickerView for first row... then do the following //
// Here.. packSizePickerView is an object of UIPickerView
if (indexPath.row == 1)
{
textField.tag=0;
textField.delegate= self;
packSizePickerView.delegate = self;
packSizePickerView = [[UIPickerView alloc] init];
packSizePickerView.autoresizingMask=UIViewAutoresizingFlexibleWidth;
packSizePickerView.showsSelectionIndicator=YES;
textField.inputView = packSizePickerView;
}
// if you want to select date / months in row 2, go for UIDatePickerView //
if (indexPath.row == 1)
{
textField.tag = 1;
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
datePicker.datePickerMode = UIDatePickerModeDate;
[datePicker addTarget:self action:#selector(datePickerValueChangedd:) forControlEvents:UIControlEventValueChanged];
datePicker.tag = indexPath.row;
textField.delegate= self;
textField.inputView = datePicker;
[datePicker release];
}
}
// Configure the cell...
NSInteger row = [indexPath row];
cell.textLabel.text = [myArray objectAtIndex:row];
return cell;
}
And for datePickerValueChangedd
- (void)datePickerValueChangedd:(UIDatePicker*) datePicker{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(100, 50, 68, 68)];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = NSDateFormatterMediumStyle;
label.text = [NSString stringWithFormat:#"%#",[df stringFromDate:datePicker.date]];
NSLog(#"I am inside the datePickerValueChanged - - %#", label.text);
[df release];
globalValue1 = label.text;
// use a global variable to copy the value from the pickerView. //
}
Now in the textFieldDidEndEditing:
-(void) textFieldDidEndEditing:(UITextField *)textField {
if (textField.tag ==0)
[textField setText: globalValue0];
if (textField.tag ==1)
[textField setText: globalValue1];
}
And to resign UIDatePicker, set the UIView as a UIControl and
resignFirstResponder
I think that you need to put your UIPickerView "outside" the viewable screen and animate it in when the button is pressed. I'm not really sure what the best way to get rid of it would be but you could probably listen for a tap on the parent view when the picker is visible and then animate it back out.