Alexey
Alexey

Reputation: 397

UITableView + UITextField + UIDatePicker

I have UIViewController and UITableViewCell with UITextField and UIDatePicker. If I change the value in the first cell UITextField I change the value in cell 1 and 7. If I change the value in the second cell UITextField I change the value in cell 2 and 8. And after the scroll value from the first cell sometimes moves in a second. Why is this happening? For cell I created a separate class which is UITextField and UIDatePicker.

My UIViewController

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
     return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
     return [self.stepsController.timeadayVal integerValue];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    addCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    cell.titleLabel.text = [NSString stringWithFormat:@"%i прием",indexPath.row+1];

    return cell;
}

UITableViewCell.m

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {

    _titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(20, 10, 320, 20)];

    _titleLabel.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:17];
    _titleLabel.textColor = [UIColor darkGrayColor];

    [self addSubview:_titleLabel];

    _textField = [[UITextField alloc]initWithFrame:CGRectMake(20, 35, 280, 35)];

    UIView *paddingView6 = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 20)];
    _textField.leftView = paddingView6;
    _textField.leftViewMode = UITextFieldViewModeAlways;

    [_textField.layer setBackgroundColor: [[UIColor colorWithRed:249.0/255.0 green:249.0/255.0 blue:249.0/255.0 alpha:1] CGColor]];
    [_textField.layer setBorderColor: [[UIColor colorWithRed:245.0/255.0 green:246.0/255.0 blue:247.0/255.0 alpha:1] CGColor]];
    [_textField.layer setBorderWidth: 0.2];
    [_textField.layer setCornerRadius:3.0f];
    [_textField.layer setMasksToBounds:YES];

    _textField.text = [NSString stringWithFormat:@"00:00"];
    _textField.font = [UIFont fontWithName:@"HelveticaNeue-Light" size:16.0];
    _textField.textColor = [UIColor grayColor];


    UIToolbar *myToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    NSMutableArray *itemsArray = [[NSMutableArray alloc] init];
    UIBarButtonItem *flexButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
    [itemsArray addObject:flexButton];
    UIBarButtonItem *doneButton =
    [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
                                                  target:self action:@selector(inputAccessoryViewDidFinish:)];

    [doneButton setTitleTextAttributes:@{
                                         UITextAttributeFont: [UIFont fontWithName:@"HelveticaNeue-Light" size:15.0],
                                         UITextAttributeTextColor: [UIColor colorWithRed:60.0/255.0 green:162.0/255.0 blue:161.0/255.0 alpha:1]
                                         } forState:UIControlStateNormal];

    [itemsArray addObject:doneButton];
    [myToolbar setItems:itemsArray animated:NO];


    UIDatePicker *timePicker = [[UIDatePicker alloc] init];
    timePicker.datePickerMode = UIDatePickerModeTime;

    [timePicker addTarget:self action:@selector(timeChanged:)
         forControlEvents:UIControlEventValueChanged];

    _textField.inputAccessoryView = myToolbar;
    _textField.inputView = timePicker;

    _textField.inputView = timePicker;

    [self addSubview:_textField];
}
return self;
}


-(void)timeChanged:(id)sender{

    UIDatePicker *picker=(UIDatePicker*)_textField.inputView;
    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"HH:mm"];
    NSString *dateString = [dateFormat stringFromDate:picker.date];

    _textField.text = dateString;

}

-(void)inputAccessoryViewDidFinish:(id)sender {

    [_textField resignFirstResponder];

}

Upvotes: 1

Views: 706

Answers (5)

Wain
Wain

Reputation: 119031

This appears to be a cell reuse problem. When you call dequeueReusableCellWithIdentifier: you may get a cell which has already been used. When this happens you need to clean out all of the old information. Currently you only set the title label text. But you also need to configure your text field and date picker (to default or saved values for the index path).

Upvotes: 1

Simon McLoughlin
Simon McLoughlin

Reputation: 8465

addCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

This function does not guarantee to return a cell, it returns any that are available to be reused, but it looks like your not setting a reuse identifier anywhere. If you use storyboards to create the layout of the cell and then refer to its cellIdentifer it will be returned by this call. However outside of that you have to create the cell and set its identifier. I would imagine you are getting some unexpected logic because of this.

Don't store a global reference to the cell either and check if the dequeue function returns nil. Like so:

static NSString *CellIdentifier = @"Cell";
UITableViewCell *addCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if(addCell == nil)
{
     addCell = [[UITableViewCell alloc] initWithStyle: <style> reuseIdentifier:CellIdentifier ];
}

...
...

It looks / sounds like your using the same cell instance in multiple locations. When one changes they all change when the cell's are refreshed. The purpose of the dequeue function is to return an new instance based off an already complied / create cell object. They need to all be separate instances.

Upvotes: 0

lbremen
lbremen

Reputation: 53

Secondly, the thing with the display bugs of the textfield is a structure problem. Check ur structure and keep in mind that evertime u scroll the cells are loading new. and if you add subviews all the time its just a mess u got like 4 views of the same textfield ans so on...... be sure that there is only just one at all time.

Upvotes: 1

lbremen
lbremen

Reputation: 53

OK, first you are mixing up some expressions in wrong context. I think i understood ur problem.

The reason for this is that if you scroll and the cell scrolls out of the screen and then you scroll back it loads again the cell-Method. So the value you changed isn't saved in this method so it calles the old value again.

Maybe you should store your changed values in temp-variables and in the method that calls the cell just do an if.

if(value != tmpValue && tmpValue != 0) 
{
   value = tmpValue;
}

Upvotes: 0

gronzzz
gronzzz

Reputation: 615

Please write a couple of code. Anyway i think the best practice for you is to create UIViewController, then uiview instead of uitableviewcell, then in uiview add uitextfield and date picker, because cells are for uitableview. Also i don't understand how much cells you have, mb better to create uitableview with cells instead of uiviewcontroller. Your bug in your code, please post him in update. Look at the tags and how you migrate your data. so update please.

Upvotes: 0

Related Questions