简体   繁体   中英

UITableView: `tableView:cellForRowAtIndexPath:` not called for all rows

I have created a UITableView with 4 Sections and 3 Rows so totally 12 Rows. But

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

The above method only gets called for 9 times instead of 12 times. Why this happening? My 4th section is not getting constructed but my 1st section gets duplicated as 4th section.

Please refer my code below

@interface MainViewController : UITableViewController<UITextFieldDelegate,UITableViewDelegate,UITableViewDataSource>
 {
}
@end


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad 
{
  CGRect frameRect = CGRectMake(0,0,320,460);

  UITableView *tableView = [[UITableView alloc] initWithFrame:frameRect   
  style:UITableViewStyleGrouped];
  tableView.delegate = self;
  tableView.dataSource = self;  
  tableView.backgroundColor = [UIColor purpleColor];
  tableView.scrollEnabled = YES;

  self.view = tableView;
  [tableView release];

  [super viewDidLoad];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    return 3;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 4;
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
     NSLog(@"CELL IS NIL %i", indexPath.section);

  static NSString *CellIdentifier = @"Cell";
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if (cell == nil)
  {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

      if (indexPath.section == 0)
      {
          if(indexPath.row == 0)
          {
              cell.text = @"Tmail";

              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
          else if ( indexPath.row == 1 )
          {
              cell.text = @"English";
              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
          else
          {
              cell.text = @"Hindi";
              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
      }
      else if (indexPath.section == 1)
      {
          if(indexPath.row == 0)
          {
              cell.text = @"Street";

              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
          else if ( indexPath.row == 1 )
          {
              cell.text = @"City";
              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
          else
          {
              cell.text = @"State";
              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
      }
      else if (indexPath.section == 2)
      {
          if(indexPath.row == 0)
          {
              cell.text = @"Salem";

              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
          else if ( indexPath.row == 1 )
          {
              cell.text = @"Samalpatti";
              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
          else
          {
              cell.text = @"Chennai";
              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
      }

      else if (indexPath.section == 3)
      {
          if(indexPath.row == 0)
          {
              cell.text = @"NOKIA";
              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
          else if ( indexPath.row == 1)
          {
              cell.text = @"SAMSUNG";
              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
          else
          {
              cell.text = @"SONY";
              UITextField *aField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];
              aField.placeholder = @"Mandatory";
              aField.delegate = self;
              aField.textColor = [UIColor blackColor];
              [cell addSubview:aField];
              [aField release];
          }
      }
   }

  return cell;
}

在此处输入图片说明

actually when you scroll then other rows are created in case you having more rows,so think you need to write this code like this,

Edited one

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    {
         NSLog(@"CELL IS NIL %i", indexPath.section);

      static NSString *CellIdentifier = @"Cell";
if (cell == nil) 
    {

        CGRect CellFrame = CGRectMake(0, 0, 300, 70);
        cell = [[[UITableViewCell alloc] initWithFrame:CellFrame reuseIdentifier:CellIdentifier] autorelease];
        CGRect labLabelFrame = CGRectMake(5, 5, 250, 40);
        UILabel *lblTemp;

        lblTemp = [[UILabel alloc] initWithFrame:labLabelFrame];
        lblTemp.tag = 1;
        [cell.contentView addSubview:lblTemp];
        [lblTemp release];

        CGRect textFieldFrame= CGRectMake(200, 5, 120, 30);

        UITextField *txt=[[UITextField alloc] initWithFrame:textFieldFrame];
        text.tag=2;
        [cell.contentView addSubview:txt];
        [txt release];

    }
     UILabel *cellLabel = (UILabel *)[cell viewWithTag:1];
      UITextField *aField=(UITextField *)[cell viewWithTag:2];

    aField.text=@"";
    aField.placeholder=@"";
if (indexPath.section == 0)
              {
                  if(indexPath.row == 0)
                  {
                      cellLabel.text = @"Tmail";


                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];

                  }
                  else if ( indexPath.row == 1 )
                  {
                      cellLabel.text = @"English";

                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];


                  }
                  else
                  {
                      cellLabel.text = @"Hindi";

                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];


                  }
              }
              else if (indexPath.section == 1)
              {
                  if(indexPath.row == 0)
                  {
                      cellLabel.text = @"Street";


                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];

                  }
                  else if ( indexPath.row == 1 )
                  {
                      cellLabel.text = @"City";

                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];


                  }
                  else
                  {
                      cellLabel.text = @"State";

                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];

                  }
              }
              else if (indexPath.section == 2)
              {
                  if(indexPath.row == 0)
                  {
                      cellLabel.text = @"Salem";
                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];

                  }
                  else if ( indexPath.row == 1 )
                  {
                      cellLabel.text = @"Samalpatti";

                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];


                  }
                  else
                  {
                      cellLabel.text = @"Chennai";

                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];


                  }
              }

              else if (indexPath.section == 3)
              {
                  if(indexPath.row == 0)
                  {
                      cellLabel.text = @"NOKIA";

                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];

                  }
                  else if ( indexPath.row == 1)
                  {
                      cellLabel.text = @"SAMSUNG";

                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];


                  }
                  else
                  {
                      cellLabel.text = @"SONY";

                      aField.placeholder = @"Mandatory";
                      aField.delegate = self;
                      aField.textColor = [UIColor blackColor];

                  }
              }


          return cell;
        }

Problem with your code is:

1) Cell is being reused. but the textfield what you added as subview is not removed!

2) Whenever your cellforRowAtIndex gets called, you are adding textfield each time. But you forgot that you have already added one textfield but haven't removed it.

  • This is the reason for overlapping.

Solution: Subclass the UITableViewCell and add textfield in its initWithFrame method and pass the data to that cell. This will solve your problem and also this will reduce your cellForRowAtIndex method length.

Sample code: CustomCell.h:

#import <UIKit/UIKit.h>

@class contactr;
@interface CustomTableCell : UITableViewCell 
{
    UITextField *mTextField;
}
@property(nonatomic , retain) UITextField *textField;

@end

CustomCell.m:

#import "CustomTableCell.h"
@synthesize textField = mTextField;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) 
    {       
        UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(100,10,200,40)];

        self.textField = textField;
        [textField release];
        [self addSubview:self.textField];

    }
    return self;
}

- (void)dealloc 
{
    self.textfield = nil;
    [super dealloc];
}


@end

Use this class as your tableViewCell.

And your cellForRowAtIndex must be:

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
     NSLog(@"CELL IS NIL %i", indexPath.section);

  static NSString *CellIdentifier = @"Cell";
  CustomTableCell *cell = (CustomTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if (cell == nil)
  {


    cell = [[[CustomTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

   }
 cell.textField.placeholder = @"";
 cell.textField.text = @"";
      if (indexPath.section == 0)
      {
          if(indexPath.row == 0)
          {
              cell.text = @"Tmail";
              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;
          }
          else if ( indexPath.row == 1 )
          {
              cell.text = @"English";
              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;
          }
          else
          {
              cell.text = @"Hindi";
              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;
          }
      }
      else if (indexPath.section == 1)
      {
          if(indexPath.row == 0)
          {
              cell.text = @"Street";
              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;
          }
          else if ( indexPath.row == 1 )
          {
              cell.text = @"City";
              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;
          }
          else
          {
              cell.text = @"State";
              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;

          }
      }
      else if (indexPath.section == 2)
      {
          if(indexPath.row == 0)
          {
              cell.text = @"Salem";

              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;
          }
          else if ( indexPath.row == 1 )
          {
              cell.text = @"Samalpatti";
              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;
              cell.textField.textColor = [UIColor blackColor];

          }
          else
          {
              cell.text = @"Chennai";
              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;
              cell.textField.textColor = [UIColor blackColor];

          }
      }

      else if (indexPath.section == 3)
      {
          if(indexPath.row == 0)
          {
              cell.text = @"NOKIA";
              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;
              cell.textField.textColor = [UIColor blackColor];
          }
          else if ( indexPath.row == 1)
          {
              cell.text = @"SAMSUNG";
              cell.textField.placeholder = @"Mandatory";
              cell.textField.delegate = self;
              cell.textField.textColor = [UIColor blackColor];
          }
          else
          {
              cell.text = @"SONY";
              cell.textField.placeholder = @"Mandatory";
             cell.textField.delegate = self;
              cell.textField.textColor = [UIColor blackColor];
          }
      }




  return cell;
}

From your initial code, the tableview is behaving normally.
You create cells for the first 3 sections because they are visible and there are no extra cell in the table view which you can reuse.
But, whenever you get scroll to the 4th section (which is not visible at first), you start reusing cells (which happen to be the ones from the 1st section that is not out of the screen).

In order not to lose the data the user has entered in each cell you need to store each UITextField(or at least the text from it) in a separate array. When the table needs a certain cell, you look for the textfield in your array. If it's not there, create and add a new UITextField.

PS: I hope the code doesn't have any typos. I'm at work and I don't have a mac here.



@interface MainViewController : UITableViewController
 {
 NSMutableArray* textFields;
}
@end

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad 
{
  CGRect frameRect = CGRectMake(0,0,320,460);

  UITableView *tableView = [[UITableView alloc] initWithFrame:frameRect   
  style:UITableViewStyleGrouped];
  tableView.delegate = self;
  tableView.dataSource = self;  
  tableView.backgroundColor = [UIColor purpleColor];
  tableView.scrollEnabled = YES;

  self.view = tableView;
  [tableView release];

  [super viewDidLoad];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    // Return the number of rows in the section.
    return 3;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    // Return the number of sections.
    return 4;
}

- (UITextField*)getTextFieldAtIndexPath:(NSIndexPath*)indexPath
{
    if (textFields == nil)
      textFields = [[NSMutableArray alloc] init];

    // Add padding, just in case UITableView doesn't need the cells in order
    while (indexPath.section >= [textFields count])
    {
        [textFields addObject:[NSNull null]];
    }

    // Get the section list
   NSMutableArray* sectionList = [textFields objectAtIndex:indexPath.section]; 

   if (sectionList == [NSNull null])
   {
     sectionList = [[[NSMutableArray alloc] init] autorelease];
     [textFields replaceObjectAtIndex:indexPath.section withObject:sectionList];
   }


   // Now that we have the section list, we need to do the same for the row
    while (indexPath.row >= [sectionList count])
    {
        [sectionList addObject:[NSNull null]];
    }

    UITextField* afield = [sectionList objectAtIndex:indexPath.row];

    if (afield == [NSNull null])
    {
      // If there was no afield stored there, just create a new one  
      afield = [[UITextField alloc] initWithFrame:CGRectMake(100,10,200,40)];
      afield.placeholder = @"Mandatory";
      afield.delegate = self;
      afield.textColor = [UIColor blackColor]; 

      [sectionList replaceObjectAtIndex:indexPath.row withObject:aField];

      [afield release];
    }

    return afield;
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
     NSLog(@"CELL IS NIL %i", indexPath.section);

  static NSString *CellIdentifier = @"Cell";
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  UITextField *aField;

 // If we can't reuse the cell, just create a new one
  if (cell == nil)
  {
      cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  }
  else
  {
      // if we are reusing the cell, just remove the old textField to make room for the new one
      [[cell.contentView viewForTag:1234] removeFromSuperview];
  }

  // Get the text field for this cell. The method below will create a new one if it doesn't exist, or just return the existing one if found.
  aField = [self getTextFieldAtIndexPath:indexPath];

  // Just add this textfield to the cell
  [cell.contentView addSubView:aField];

  // Now that we added the textfield, we only need to set the title of the cell. The content of the textField will be cached and moved around.

      if (indexPath.section == 0)
      {
          if(indexPath.row == 0)
              cell.text = @"Tmail";
          else if ( indexPath.row == 1 )
              cell.text = @"English";
          else
              cell.text = @"Hindi";
      }
      else if (indexPath.section == 1)
      {
          if(indexPath.row == 0)
              cell.text = @"Street";
          else if ( indexPath.row == 1 )
              cell.text = @"City";
          else
              cell.text = @"State";
      }
      else if (indexPath.section == 2)
      {
          if(indexPath.row == 0)
              cell.text = @"Salem";
          else if ( indexPath.row == 1 )
              cell.text = @"Samalpatti";
          else
              cell.text = @"Chennai";
      }

      else if (indexPath.section == 3)
      {
          if(indexPath.row == 0)
              cell.text = @"NOKIA";
          else if ( indexPath.row == 1)
              cell.text = @"SAMSUNG";
          else
              cell.text = @"SONY";
      }
   }

  return cell;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM