5

This question has been bugging me a LOT lately. Any help would be appreciated.

These were my objectives:

  1. Setup a UIDatePickerView for a UItextField in a UITableViewCell.

I have done all this so far, and I can see the picker working fine. Whenever I change the picker Value, I use NSLog to display the current value and it is working fine for every change.

This is what I want: ** Whenever I change the pickervalue, I need the value to also be changed automatically in the UITextField (which is in the UITableViewCell)**

This is my CellForRowIndexPath code:

- (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];
    UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(110, 10, 185, 30)];
    textField.clearsOnBeginEditing = YES;
    textField.textAlignment = UITextAlignmentRight;

    [cell.contentView addSubview:textField];
     UIDatePicker *datePicker = [[UIDatePicker alloc] init];
        datePicker.datePickerMode = UIDatePickerModeDate;
        [datePicker addTarget:self action:@selector(datePickerValueChangedd:) forControlEvents:UIControlEventValueChanged];
        datePicker.tag = indexPath.row;
        textField.inputView = datePicker;

        NSDateFormatter *df = [[NSDateFormatter alloc] init];
        df.dateStyle = NSDateFormatterMediumStyle;
        NSString *local;
        local = [self datePickerValueChangedd: datePicker];  
        NSLog(@"%@", local); //DISPLAYS OUTPUT ONCE
        textField.text =local;
        [datePicker reloadInputViews];
        [datePicker release];




// Configure the cell...

NSInteger row = [indexPath row];
cell.textLabel.text = [doseInfoDetailsArray objectAtIndex:row];

return cell;
 }

I am also posting other code below.

- (NSString *)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(@"%@", label.text); // DISPLAYS OUTPUT WHENEVER PICKER IS MOVED
doseInfoDetailsTable.reloadData;
return (label.text);
//[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(t) name:TestNotification object:label];
[df release];

}

Output displays correctly. But I need it to change in the UITextField also.

    2011-06-01 17:32:23.740 Tab[13857:207] Jun 1, 2017
    2011-06-01 17:32:23.740 Tab[13857:207] Jun 1, 2017
    2011-06-01 17:32:25.321 Tab[13857:207] Dec 1, 2017
    2011-06-01 17:44:51.453 Tab[13857:207] Jun 1, 2017
    2011-06-01 17:44:52.605 Tab[13857:207] Jun 1, 2018
    2011-06-01 17:44:53.467 Tab[13857:207] Jun 2, 2018
    2011-06-01 17:44:54.247 Tab[13857:207] Jun 5, 2018
csano
  • 13,266
  • 2
  • 28
  • 45
Legolas
  • 12,145
  • 12
  • 79
  • 132

2 Answers2

9

You don't need to instantiate multiple instances of UIDatePicker. One should do. Assign it to all the text fields. Now to update the text field, you will have to identify which text field is being updated. For this you should adopt the UITextFieldDelegate protocol and implement the textFieldDidBeginEditing: method to set the active text field. Now, when the value is changed on the UIDatePicker instance, update the active text field.

But this is sadly not enough. You will face a problem with cell reuse. To counter this, you will have to maintain an array of dates for each of your rows and update the array every time the value is changed on the UIDatePicker instance. You can identify which cell the text field belongs to by either tagging it or by getting the superview which would be a UITableViewCell instance and then calling indexPathForCell: method on the UITableView.

And on a side note, return (label.text); [df release]; is wrong as the method will return prior to df being released. You should swap the order there.

Deepak Danduprolu
  • 44,595
  • 12
  • 101
  • 105
  • @Siddharth & @Deepak : You guys are my favorite people on StackOverflow. Is there any way to IM you guys on StackOverflow and ask questions (or) notify you whenever I post one ? Please allow me to try out the solution @Deepak has provided and I will give it a Thumbs Up and a Tick :) thanks. – Legolas Jun 01 '11 at 23:00
  • Lol well I'm glad you think so, but there are tonnes of other users who know a lot more than I do :) Either way I don't think SO has any IM options, but I'm on SO for most of the day so one way or the other I will definitely come across your questions. That being said, the response rate for well framed questions on SO is very good so you won't go without help for long :) – Sid Jun 01 '11 at 23:43
  • http://stackoverflow.com/questions/6219289/customizing-self-navigationitem-rightbarbuttonitem-self-editbuttonitem-help – Legolas Jun 02 '11 at 19:28
  • Hey guys. Could you help me with my question on UISearchBars ? http://stackoverflow.com/questions/6253827/change-the-width-of-uisearchbars-on-a-tableview – Legolas Jun 06 '11 at 15:40
  • Hey guys, I have a question about the accepted answer. I have implemented the `textFieldDidBeginEditing:` method to get the current `UITextField`, but how would I update that field from the `datePickerValueChanged` method? – AngeloS Jun 06 '11 at 20:10
  • You will have to use the `setTarget:action:forControlEvents:` for the control event `UIControlEventValueChanged`. – Deepak Danduprolu Jun 06 '11 at 20:14
  • Thank you for your response. Yep, I set that up how @Legolas has it in the code to direct to the method `datePickerValueChanged` on the `UIDatePicker` .. that works fine, as I can get the output as he showed in his post. I guess I'm having issues with how do you make the jump from the `datePickerValueChanged` method (that catches the value of the `UIDatePicker`) to then update the actual `UITextField` that was caught by `textFieldDidBeginEditing`.. I don't see how those two methods are linked. – AngeloS Jun 06 '11 at 20:27
  • @AngeloS : Use a global variable; store data to it; and copy it back to the textField. – Legolas Jun 06 '11 at 20:29
  • Yes, I did that. I stored both the value taken from the `UIDatePicker` in the method `datePickerValueChanged` and the `UITextField` picked up from the `textFieldDidBeginEditing`. If I try this line of code it fails: `textFieldThatWillBeUpdatedByTheUIDatePicker.text = globallySavedStringTakenFromTheUIDatePicker;` with `[UITextField date]: unrecognized selector sent to instance 0x4e1a9f0` .. This is happening in the `datePickerValueChanged` method. Have you actually implemented this? If so would you mind posting some sample code? Thank you. – AngeloS Jun 06 '11 at 20:50
  • Can you post the exact method. – Deepak Danduprolu Jun 06 '11 at 20:54
  • `- (void)textFieldDidBeginEditing:(UITextField *)textField { textFieldThatWillBeUpdatedByTheUIDatePicker = (UITextField *)textField; }` Then I have: `- (NSString *)datePickerValueChanged:(UIDatePicker*) datePicker{ NSDateFormatter *df = [[NSDateFormatter alloc] init]; df.dateStyle = NSDateFormatterMediumStyle; globallySavedStringTakenFromTheUIDatePicker = [NSString stringWithFormat:@"%@",[df stringFromDate:datePicker.date]]; textFieldThatWillBeUpdatedByTheUIDatePicker.text = globallySavedStringTakenFromTheUIDatePicker;}` – AngeloS Jun 06 '11 at 21:01
  • I've also tried this: `- (void)textFieldDidBeginEditing:(UITextField *)textField { textField.text = globallySavedStringTakenFromTheUIDatePicker; }` – AngeloS Jun 06 '11 at 21:02
  • I think `datePicker` is not point to the `UIDatePicker` object based on the error. Check if you got it right in IB or are altering it somewhere. – Deepak Danduprolu Jun 06 '11 at 21:04
  • I build the `UIDatePicker` in code exactly how @Legolas has it. I'm not modifying much if anything from his code. Whats happening is that it is failing on the line `globallySavedStringTakenFromTheUIDatePicker = [NSString stringWithFormat:@"%@",[df stringFromDate:datePicker.date]];`. Stepping through the code shows that this is actually getting called twice when a date is changed. The first time around it is successful, but the second it bombs out. I would really like to see how @Legolas implemented this. Thanks again for your help. – AngeloS Jun 06 '11 at 21:10
  • Correction, I did modify his code because the original way he built the `UIDatePicker` in code failed out for me because no bounds were set. I replaced his allocation line with `UIDatePicker *datePicker = [[[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, 460.0, 216.0)] autorelease];` – AngeloS Jun 06 '11 at 21:12
  • But there is a `[datePicker release];` later on. You are releasing more than owned then. – Deepak Danduprolu Jun 06 '11 at 21:16
  • I didn't include his `[datePicker release]` – AngeloS Jun 06 '11 at 21:18
  • The code here looks ok but the error here suggests otherwise. I would like a look at your `cellForRowAtIndexPath:` too. Otherwise, it's difficult to tell. – Deepak Danduprolu Jun 06 '11 at 21:27
  • I figured out whats going on, just not sure how to correct it. All of the code is correct. What is happening is that when you force a value into the `UITextField` from the `datePickerValueChanged` method, the `datePickerValueChanged` method gets called again, because well, the date changed haha. The issue is that that because you are forcing a string value into the `UItextField` the `UIDatePicker` doesn't like this because it's not a date. Therefore, since the `UItextField` only accepts strings, how can you pass a value that the `UIDatePicker` will accept? – AngeloS Jun 06 '11 at 21:32
  • 1
    Why is a change in the `UITextField`'s value calling `datePickerValueChanged:`? If there is a `setTarget:action..` thing for it, then remove it. – Deepak Danduprolu Jun 06 '11 at 21:38
  • I removed it and it worked. Sorry about all of that. I completely missed the fact that I had the `setTarget:action..` to `datePickerValueChanged` for the `UITextField` when I was setting it up in `cellForRowAtIndexPath`.... I apologize for missing that. I am going to post some sample code though, just in case someone stumbles upon this. – AngeloS Jun 06 '11 at 21:48
  • @angelos @deepak @legolas - there was what amounted to a new question asked in the comments here. Don't be afraid to ask a new question but use this one as the basis for it (with a referencing link). Otherwise we end up with a lot of noise in the comments and flags being raised. Thanks. – Kev Jun 06 '11 at 23:24
1

This is just a follow up to a flurry of comments on the accepted solution. Thank you all for your help. To make this work, the sample code is as follows:

- (void)textFieldDidBeginEditing:(UITextField *)textField {

    textFieldThatWillBeUpdatedByTheUIDatePicker = (UITextField *)textField;

}

Where textFieldThatWillBeUpdatedByTheUIDatePicker is declared as a UITextField in the header file.

Finally, here is the method that changes the cell:

- (NSString *)datePickerValueChanged:(UIDatePicker*) datePicker{

    NSDateFormatter *df = [[NSDateFormatter alloc] init];
    df.dateStyle = NSDateFormatterMediumStyle;

    textFieldThatWillBeUpdatedByTheUIDatePicker.text = [NSString stringWithFormat:@"%@",[df stringFromDate:datePicker.date]];

}

To handle cell reuse, do what @Deepak said with regards to an array you can use this line:

[dateArray replaceObjectAtIndex:textFieldThatWillBeUpdatedByTheUIDatePicker.tag withObject:[NSString stringWithFormat:@"%@",[df stringFromDate:datePicker.date]]];

Where the tag is set in cellForRowAtIndexPath like this:

textField.tag = indexPath.row;

I'm assuming that the dateArray is pre-populated and prior to the table view getting called for the first time either with real dates or blank values. If you try to replace something that isn't there it is going to fail obviously.

Finally, when the UIDatePicker is being built in cellForRowAtIndexPath include this line to handle the cell reuse:

textField.text = [dateArray objectAtIndex:indexPath.row];

The first time around it may be blank or pre-populated with a date.

AngeloS
  • 5,536
  • 7
  • 40
  • 58
  • 1
    ideally you should be asking a new question and making a reference to this question and answer. – Kev Jun 06 '11 at 23:21