1

I'm looking to get the selected (checkmarked) rows from my UITableView and show them in my console log. This doesn't seem like it should be so difficult. I've found two methods that I'll display below. Neither work despite the logic mostly making sense to me. Which would you suggest and how can I tweak to make it work?

My TableView Code:

I don't think this is completely necessary to the issue, but I know it sometimes helps to see the whole picture.

#pragma mark - tableView datasource

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

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
    NSDictionary *tempDictionary= [self.places objectAtIndex:indexPath.row];
    
    cell.textLabel.text = [tempDictionary objectForKey:@"name"];
    
    if([tempDictionary objectForKey:@"vicinity"] != NULL)
    {
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%@",[tempDictionary   objectForKey:@"vicinity"]];
    }
    else
    {
        cell.detailTextLabel.text = [NSString stringWithFormat:@"Address Not Available"];
    }
    
    return cell;
}

//Handles tableView row selection and addition and removal of the checkmark
- (void)tableView:(UITableView *)theTableView
didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath {
    
    [theTableView deselectRowAtIndexPath:[theTableView indexPathForSelectedRow] animated:NO];
    UITableViewCell *cell = [theTableView cellForRowAtIndexPath:newIndexPath];
    if (cell.accessoryType == UITableViewCellAccessoryNone) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        // Reflect selection in data model
    } else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        cell.accessoryType = UITableViewCellAccessoryNone;
        // Reflect deselection in data model
    }
    
}

Method 1:

Add a conditional statement to the end of the checkmark handler to add/remove selections to and from an array. Then create a button action that simply calls the array and displays it in the console. I think this is clunky but could work.

  //Handles tableView row selection and addition and removal of the checkmark
- (void)tableView:(UITableView *)theTableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    [theTableView deselectRowAtIndexPath:[theTableView indexPathForSelectedRow] animated:NO];
    UITableViewCell *cell = [theTableView cellForRowAtIndexPath:indexPath];
    if (cell.accessoryType == UITableViewCellAccessoryNone) {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
        //Reflect selection in data model
    } else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
        cell.accessoryType = UITableViewCellAccessoryNone;
         //Reflect deselection in data model
    }
    
    if ([[theTableView cellForRowAtIndexPath:indexPath] accessoryType] == UITableViewCellAccessoryCheckmark) {
        [_selectedCellIndexes addObject:indexPath];
    }
}

- (IBAction)sendResults:(id)sender {
    NSLog(@"Add these: %@", _selectedCellIndexes);
    
}

Method 2:

Get the selected rows AND send to console log only when button is tapped. This seems to be the more logical method, but I can't seem to get it to work either. It doesn't throw any errors, but returns "Selected Items: (null)" in the console. What have I missed?

//Sends checkmarked items to console log
- (IBAction)sendResultsOption1:(id)sender {
    NSMutableArray *aList = [[NSMutableArray alloc] init];
    for (NSIndexPath *indexPath in _tableView.indexPathsForSelectedRows) {
        NSString *r = [NSString stringWithFormat:@"%li",(long)indexPath.row];
        [aList addObject:r];
    }
    
    NSLog(@"Selected Items: %@", _aList);
}

For what it's worth, I've also followed the instructions here without any luck.

halfer
  • 19,824
  • 17
  • 99
  • 186
jeremytripp
  • 1,038
  • 1
  • 11
  • 25

1 Answers1

2

In Method 1, your method looks like this:

- (void)tableView:(UITableView *)theTableView
    didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath {

But you're referring to indexPath in the body. You don't have an indexPath (the undeclared identifier), but you have a newIndexPath, so at a minimum, this is the start of your problems and should be fixed first.

Giving your variables the right names looks like it should work for this approach...


In Method 2, the problem is none of your table view cells are selected. In you didSelectRowAtIndexPath method, you check the accessory icon to a check mark, then you deselect the row. So there are no objects in _tableView.indexPathsForSelectedRows.

In this approach, you need to change your for loop. Instead you need to iterate through every index path, and check on the accessory icon. If it's a check mark, add it to the array. Now log the array.


As far as which approach would be preferable, it depends on how you intend to use this ultimately. Obviously, the end goal isn't to NSLog the checkmarked rows--this is an iOS app we're talking about.

nhgrif
  • 61,578
  • 25
  • 134
  • 173
  • Excellent. So I started by fixing the indexPath errors in Method 1 (edited above). Dumb mistake on my part. Also added the NSLog command and set `selectedCellIndexes` as a `NSMutableArray`, but still no results. Anything other ideas on Method 1? – jeremytripp Jan 18 '14 at 18:26
  • Also, you're right. The ultimate goal is to pass the selected row data to a database, but for now, just trying to pass it to the log! – jeremytripp Jan 18 '14 at 18:26
  • Do you want to pass them to a database only on the press of a button? If so, I'd work on method 2. You only need an array of the checkmarked rows for a short period of time. Method 2 will make your app more efficient. – nhgrif Jan 18 '14 at 18:28
  • Yeah, that's the idea anyway. But the solution for method 2 is just slightly over my head despite it probably being the better way to go. I'm going to keep at it, but still nothing so far. – jeremytripp Jan 19 '14 at 00:39