views:

49

answers:

2

Hello, Guys.

I have a UITableView in that some cells are marked with UITableViewCellAccessoryCheckmark at the initialization of the view.

When the user selects another row, I have to check if the maximum number of selected rows was achieved before. To do that, I used the code bellow:

- (NSInteger)tableView:(UITableView *)tableView numberOfSelectedRowsInSection:(NSInteger)section{

 NSInteger numberOfRows         = [self tableView:tableView numberOfRowsInSection:section];
 NSInteger numberOfSelectedRows = 0;

 for (int i = 0; i < numberOfRows; i++) {

  UITableViewCell *otherCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:section]];

  if (otherCell.accessoryType == UITableViewCellAccessoryCheckmark) {
   numberOfSelectedRows++;
  }  
 }

 return numberOfSelectedRows;

}

If my number of rows is, as example, 20, the variable numberOfRows is setted correctly with 20. Lets say that 13 rows already are marked with UITableViewCellAccessoryCheckmark. So, numberOfSelectedRows should be 13 after the loop, but only the marked and VISIBLE cells are considered. So, if I have 9 cells showed and 7 are marked, the numberOfSelectedRows returns 7 instead of 13 (but the for iterate 20 times, as expected).

Is this a correct behavior of UITableView or it is a bug of iPhone simulator?

Thanks in advance.

+2  A: 

Yes, it works as designed. You should never store model data in your views. UITableView knows nothing about the data, it only displays cells (and throws them aways as soon as they scroll off the screen). You need to store the checkmark state of each cell in a model object (e.g. an array) that you then access from your view controller.

Ole Begemann
+1  A: 

Hi This is correct behavior. The UITableView is not a list. The system caches cell that are off screen to save memory and CPU and they can not be iterated over in a manner that makes sense.

Ok, you should keep track of the model/data and the tableView will keep track of displaying it. I have had some problems with this until I accepted that uitableView is not a list:)

So, have an array of objects that each corresponds to the data in the a cell. When building the individual cells like this:

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

    static NSString *CellIdentifier = @"categoryCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }

    Item *item = [self.itemList objectAtIndex:indexPath.row];

    [cell.textLabel setText:[item itemBrand]]; //notice that here we set the cell values

    return cell;
}

The when a user clicks you change you model like this:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    NSLog(@"IndexPat.row%i", indexPath.row);
    Item item = (Item*) [self.itemList objectAtIndex:indexPath.row];
    //change the state of item
}

This way the tableView will update to resemble the model/data, you just managed the model.

RickiG