0

I have an iPad app (XCode 4.6, ARC, Storyboards, iOS 6.2.3). I have a UIPopover with a UITableView that has 21 rows in it. I can set the accessoryType in all of the rows randomly, but only in the first 12 rows does the accessoryType setting (checkmark) persist so it can be examined in another method and processed. I don't see any difference between the first 12 rows and the last 9 rows. The UITableView is scrollable, so to get to the rows after the 11th row, you have to scroll to the bottom

Here is the code to set the accessoryType:

#pragma mark didSelectRowAtIndexPath

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

    //  get the cell that was selected
    UITableViewCell *theCell = [tableView cellForRowAtIndexPath:indexPath];

    if(theCell.accessoryType != UITableViewCellAccessoryCheckmark)
        theCell.accessoryType = UITableViewCellAccessoryCheckmark;
    else
        theCell.accessoryType = UITableViewCellAccessoryNone;
}

Here is the code where I check the accessoryType and process it:

-(void) moveServices  {  //  (moves checked tableViewRows to services tableview)

NSMutableString *result = [NSMutableString string];

for (int i = 0; i < [servicesArray count]; i++) {
    NSIndexPath *path = [NSIndexPath indexPathForRow:i inSection:0];
    [tvServices scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionMiddle animated:NO];

    UITableViewCell *cell = [tvServices cellForRowAtIndexPath:path];
    if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        [result appendFormat:@"%@, ",cell.textLabel.text];
    NSLog(@"\n\ni: %d\ncell.accessoryType: %d\ncell.textLabel: %@",i,cell.accessoryType, cell.textLabel);
    }
}

if (result.length > 2) {  //  move to text box in main menu
    storeServices =[result substringToIndex:[result length] - 2];
}

}

SpokaneDude
  • 4,856
  • 13
  • 64
  • 120

1 Answers1

0

It looks like you're mixing the notion of "data source" and the contents of the cells in the table. Don't do that -- keep your data source (whether or not a particular row in the table should display a checkmark based on your program logic) separate from the settings of particular cells (whether or not a particular cell displays a checkmark). Then in cellForRowAtIndexPath, you build the cell to match your data source's current settings. The reason is that UITableView reuses cell instances based on which rows are visible on-screen (and it's just good MVC design).

In your case you should keep an NSMutableArray property in your class that records the settings for the entire table, and use the value from that array in cellForRowAtIndexPath to set up that particular cell. Then the other "business logic" methods in your controller use the array property to query your model state instead of the cell settings (which are part of the view and should be independent from the data model).

Bogatyr
  • 19,255
  • 7
  • 59
  • 72
  • Then why does it work for the first 12 rows, and not the remaining rows? – SpokaneDude Jul 17 '13 at 16:31
  • It only "works" by luck. Because those 12 rows are the ones that are (currently) visible and thus UITableView has created cells for them. Once you scroll down sufficiently far, the range of rows for which doing that "works" will change. That's why you don't do that. Keep your datasource separate from your view, that's how UITableView is designed, follow that and all will be well. – Bogatyr Jul 17 '13 at 16:34
  • OK... I understand exactly what you are saying... however, I don't know what I have to change in my code to accommodate your suggestion. Can you point me to an example or a doc? – SpokaneDude Jul 17 '13 at 16:44
  • I found [this](http://stackoverflow.com/questions/5370311/uitableview-didselectrowatindexpath-add-additional-checkmark-at-tap), which explains exactly what I have to do... I need to keep an array with the status of each row... – SpokaneDude Jul 17 '13 at 17:48