Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Rookie ios question. I am trying to create a sign up form using a table view controller. I am trying add textfields to each cell programmatically in the cellForRowAtIndexPath method but all my text fields seem to getting created on the first cell - one overlapping the other. Here is my code.

Here is how my cells are rendering. I think I am doing something goofy with the part that is reusing the cells. I did check some some other similar threads on stackoverflow but none of them helped. Could you please tell me what i am missing or is this even the way this is supposed to be done. Your inputs are really appreciated.

Thanks, Mike

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"signUpFields" forIndexPath:indexPath];

// Configure the cell...
if (indexPath.row == 0){
    //self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
    self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.firstName.placeholder = @"First Name";
    self.firstName.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.firstName setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.firstName;
    [cell.contentView addSubview:self.firstName];
}

if (indexPath.row == 1){
    self.lastName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.lastName.placeholder = @"Last Name";
    self.lastName.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.lastName setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.lastName;
    [cell.contentView addSubview:self.lastName];
}

if (indexPath.row == 2){
    self.emailId = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.emailId.placeholder = @"Email Id";
    self.emailId.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.emailId setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.emailId;
    [cell.contentView addSubview:self.emailId];
}

if (indexPath.row == 3){
    self.password = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.password.placeholder = @"Password";
    self.password.secureTextEntry = YES;
    self.password.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.password setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.password;
    [cell.contentView addSubview:self.password];
}

self.firstName.delegate = self;
self.lastName.delegate = self;
self.emailId.delegate = self;
self.password.delegate = self;

[self.signUpTable addSubview:self.firstName];
[self.signUpTable addSubview:self.lastName];
[self.signUpTable addSubview:self.emailId];
[self.signUpTable addSubview:self.password];

cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;

}
share|improve this question
 
Why not create custom UITableViewCell? and implement prepareForReuse function to reset cell data. further info in apple doc developer.apple.com/library/ios/#documentation/userexperience/… –  Jerry Juang Jul 17 '13 at 6:18
 
why are you adding your UITextFields to the tableView? –  Matthias Bauch Jul 17 '13 at 6:21
add comment

8 Answers

up vote 0 down vote accepted

Try this..

     - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString *CellIdentifier = @"Cell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }

       if (indexPath.row == 0){
    //self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
    self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.firstName.placeholder = @"First Name";
    self.firstName.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.firstName setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.firstName;
    [cell addSubview:self.firstName];
}

if (indexPath.row == 1){
    self.lastName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.lastName.placeholder = @"Last Name";
    self.lastName.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.lastName setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.lastName;
    [cell addSubview:self.lastName];
}

if (indexPath.row == 2){
    self.emailId = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.emailId.placeholder = @"Email Id";
    self.emailId.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.emailId setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.emailId;
    [cell addSubview:self.emailId];
}

if (indexPath.row == 3){
    self.password = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.password.placeholder = @"Password";
    self.password.secureTextEntry = YES;
    self.password.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.password setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.password;
    [cell addSubview:self.password];
}

self.firstName.delegate = self;
self.lastName.delegate = self;
self.emailId.delegate = self;
self.password.delegate = self;


cell.selectionStyle = UITableViewCellSelectionStyleNone;

        return cell;
    }

no need to add again text view in table view this is wrong. try this this will work for you but better you create custom Cell and use that is the best way to do it because you can use what ever you want with Cell.

share|improve this answer
 
This worked. Thank you! –  Mike G Jul 17 '13 at 7:09
add comment

Looks like you have just four cells you want to display. This is a static case, the cells don't change, you should create this tableView and its cells statically in the xib/storyboard. That is the preferred way here.

If you really want to do it programmatically, create four UITableViewCells with the behavior you want before hand. Keep them in an array. Inside cellForRowAtIndex path return cellArray[indexPath.row];

Note this is the best approach only because you have just four tableViewCells. ReuseIdentifiers come in handy only if you have more cells than can be accommodated on the screen at once. So in your case, you never actually reuse the cells.

share|improve this answer
add comment

Don't add them as subviews, set them as the cell's accessory view.

- (UITextField*)getTextField{
    UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 20, 35)];
    tf.delegate = self;
    tf.textColor        = [UIColor colorWithRed:.231 green:.337 blue:.533 alpha:1];
    tf.autocorrectionType = UITextAutocorrectionTypeNo;
    tf.borderStyle = UITextBorderStyleNone;
    tf.frame = CGRectMake(0, 20, 170, 30);
    tf.clearButtonMode = UITextFieldViewModeWhileEditing;
    tf.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
    tf.font = [UIFont systemFontOfSize:13];
    return tf;
}

- (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];
        cell.textLabel.font = [UIFont systemFontOfSize:13];
        cell.detailTextLabel.font = [UIFont systemFontOfSize:13];
        cell.detailTextLabel.numberOfLines = 2;
    }

    if (indexPath.section == 0) {

        UITextField *tf = (UITextField*)cell.accessoryView;
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.textLabel.numberOfLines = 2;
        tf                  = [self getTextField];
        cell.accessoryView = cell.editingAccessoryView = tf;
        [((UITextField*)cell.accessoryView) setBorderStyle:self.tableView.editing ? UITextBorderStyleRoundedRect : UITextBorderStyleNone];
        [((UITextField*)cell.accessoryView) setUserInteractionEnabled:self.tableView.editing ? YES : NO];
        [((UITextField*)cell.accessoryView) setTextAlignment:!self.tableView.editing ? UITextAlignmentRight : UITextAlignmentLeft];
        ((UITextField*)cell.accessoryView).tag = indexPath.row;
    }

    return cell;
}

The idea is that the cell is re-drawn each time it appears on screen, coming from off the screen and if you add the text field with addSubview:, it will add it each time as well. You COULD do it, but then you have to clear the cell's contentView of subviews, but that requires extra work, cpu and memory use, and not to say it's the least elegant solution.

share|improve this answer
add comment

keep this one and try it,

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *MyIdentifier = [NSString stringWithFormat:@"%d%d",indexPath.row,indexPath.section];


    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

    if (cell == nil)
    {
     //your stuff.
    }
}
share|improve this answer
add comment

Try to use this one ...And there is no need to add these textfield to tableview. So please remove some code..

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"signUpFields" forIndexPath:indexPath];

// Configure the cell...
if (indexPath.row == 0){
    //self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(5, 0, 280, 21)];
    self.firstName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.firstName.placeholder = @"First Name";
    self.firstName.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.firstName setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.firstName;
    [cell addSubview:self.firstName];
}

if (indexPath.row == 1){
    self.lastName = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.lastName.placeholder = @"Last Name";
    self.lastName.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.lastName setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.lastName;
    [cell addSubview:self.lastName];
}

if (indexPath.row == 2){
    self.emailId = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.emailId.placeholder = @"Email Id";
    self.emailId.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.emailId setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.emailId;
    [cell addSubview:self.emailId];
}

if (indexPath.row == 3){
    self.password = [[UITextField alloc] initWithFrame:CGRectMake(120, 13, 375, 30)];
    self.password.placeholder = @"Password";
    self.password.secureTextEntry = YES;
    self.password.autocorrectionType = UITextAutocorrectionTypeNo;
    [self.password setClearButtonMode:UITextFieldViewModeWhileEditing];
    //cell.accessoryView = self.password;
    [cell addSubview:self.password];
}

self.firstName.delegate = self;
self.lastName.delegate = self;
self.emailId.delegate = self;
self.password.delegate = self;

cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;

}
share|improve this answer
add comment

Instead of writing more cells just create one custom cell with textfield.Give the tag for each textfield and also set the count of rows in numberOfRowsIntheSections then it will display the cells how much you need. I think it will helps you.

share|improve this answer
add comment

Before You follow my Answer i wnat to tell you that following code is bad for memory management because it will create new cell for each rows of UITableView, so be careful for it.

But it is better to use, When UITableView Have Limited rows (about 50-100 may be ) then following code is helpful in your case, use it, If it is suitable for you.

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    NSString *CellIdentifier = [NSString stringWithFormat:@"S%1dR%1d",indexPath.section,indexPath.row];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil)
    {
        cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];


         /// Put/Create  your UITextField or any Controls here


     }

    return cell;
}
share|improve this answer
add comment

@Mike : First of all I will suggest you to go with StoryBoard or Nib files.

If you use this, then you can use following code

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

     UITextField *txtField = (UITextField *)[cell viewWithTag:1];
     txtField.text = @"Latest";

     return cell;
}

Based on row number you can set text.

If you want to add the UITextField at run time. then you can use following code.

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
     UITextField *txtField = [[UITextField alloc] initWithFrame:CGRectMake(165.0, 7.0, 150.0, 30.0)];
     txtField.text = @"Latest";
     [cell.contentView addSubview:txtField];
     return cell;
}

You can assign different tag and based on tags you can store those values.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.