user2289379
user2289379

Reputation:

how to I observe cell accessory Type UITableViewCellAccessoryCheckmark is checked or not?

How do I observe cell accessory Type UITableViewCellAccessoryCheckmark is checked or not?

In my app I added UITableView in a UIAlertView. I also used

cell.accessoryType = UITableViewCellAccessoryCheckmark;

In my tableView, i have 9 rows. When the user taps on first row then all rows become checked except second row. The user can check any row/rows as he wishes. When the user taps on the second row then only the second row is checked.

Thanks in Advance :)

Upvotes: 1

Views: 1318

Answers (4)

Carl Veazey
Carl Veazey

Reputation: 18363

I know this has already been answered, but I've had a lot of luck maintaining a NSMutableIndexSet instance, and adding / removing indexes for checked / unchecked rows.

The key methods:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"CellIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (!cell)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    NSInteger index = indexPath.row;
    cell.accessoryType = ([self.selectedRowsIndexSet containsIndex:index]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
    cell.textLabel.text = [NSString stringWithFormat:@"Row %d",index];

    return cell;
}

This is fairly straight-foward - check to see if the index is selected and set the accessory accordingly.

For a multi-select (i.e. any call can be selected) implementation of tableView:didSelectRowAtIndexPath: looks like this:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSInteger index = indexPath.row;
    if ([self.selectedRowsIndexSet containsIndex:index])
        [self.selectedRowsIndexSet removeIndex:index];
    else
        [self.selectedRowsIndexSet addIndex:index];

    [tableView reloadRowsAtIndexPaths:@[ indexPath ] withRowAnimation:UITableViewRowAnimationAutomatic];
}

Just add the index, reload the table. For a single select it's pretty quick too

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSInteger oldIndex = [self.selectedRowsIndexSet firstIndex];
    NSInteger newIndex = indexPath.row;
    [self.selectedRowsIndexSet removeIndex:oldIndex];
    [self.selectedRowsIndexSet addIndex:newIndex];
    [tableView reloadRowsAtIndexPaths:@[ indexPath, [NSIndexPath indexPathForRow:oldIndex inSection:0] ]
                     withRowAnimation:UITableViewRowAnimationAutomatic];
}

Can of course get more complicated with more sections, whether selections in some sections depend on selections in others, and so on. I've been using per-section arrays of index sets for the former and then various complex logic involving the underlying data model for the latter. But keeping the basic table view interaction at the level of just querying an index set helps keep these methods pretty short and readable.

Upvotes: 0

Viral Narshana
Viral Narshana

Reputation: 1877

if ([[tableView cellForRowAtIndexPath:indexPath ] accessoryType] == UITableViewCellAccessoryCheckmark){

}
else{ 

}

Upvotes: 0

Mundi
Mundi

Reputation: 80271

While the answer of @dasblinkenlight is certainly more elegant, it might be too advanced for you.

The essence is to keep track of which cells are checked and which are unchecked. Whenever something changes, reload the table view to updated the checkmarks.

You need to create your own variable to track this. A bitmap is very economical and elegant, but it might be difficult to understand and not scalable to a large number of rows. Alternatively, you could use an array.

NSMutableArray *checkedArray = [NSMutableArray arrayWithObjects:
                   [NSNumber numberWithBool:YES],
                   [NSNumber numberWithBool:NO],
                   [NSNumber numberWithBool:NO],
                   [NSNumber numberWithBool:NO],
                   [NSNumber numberWithBool:NO],
                   [NSNumber numberWithBool:NO],
                   [NSNumber numberWithBool:NO],
                   [NSNumber numberWithBool:NO],
                   [NSNumber numberWithBool:NO],
                   nil];

To change a row given the index path:

[checkedArray replaceObjectAtIndex:indexPath.row 
                        withObject:[NSNumber numberWithBool:YES]]; //add

[checkedArray replaceObjectAtIndex:indexPath.row 
                        withObject:[NSNumber numberWithBool:NO]]; //remove

And in cellForRowAtIndexPath make sure you set the accessory explicitly:

if ([[checkedArray objectAtIndex:indexPath.row] boolValue]) {
    cell.accessoryType = UITableViewCellAccessoryTypeCheckmark;
} 
else {
    cell.accessoryType = UITableViewCellAccessoryTypeNone;
}

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726929

Since the number of items is so small, you can model the checked/unchecked state with a single integer and bitmasks. Use the lower nine bits of the number to indicate a checked/unchecked state:

// Add an instance variable to your view controller
// Initialize to 0 in the designated initializer
NSUInteger checkedFlags;

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *res = ... // Dequeue the cell and so on

    res.accessoryType = (checkedFlags & (1 << indexPath.row))
    ?    UITableViewCellAccessoryCheckmark
    :    UITableViewCellAccessoryNone;

    ... // The rest of the method
}

Here is how you check/uncheck/toggle an individual row: in the tableView:willSelectRowAtIndexPath: of your delegate, do one of these:

checkedFlags |= (1 << indexPath.row); // Check
checkedFlags &= ~(1 << indexPath.row); // Uncheck
checkedFlags ^= (1 << indexPath.row); // Toggle

If you want to check/uncheck multiple rows at once, mask with a number composed of the bits corresponding to rows being checked/unchecked in the binary form For example, the number that has bits 2..8 set is 0x01FC0.

checkedFlags |= 0x1FC0; // Check rows #3 through #9

Don't forget to call reloadData after manipulating the checkedFlags variable.

Upvotes: 1

Related Questions