3

I'm using a UISwitch in the accessoryView of a UITableViewCell.

The switch uses target-action to communicate when it has been selected or deselected:

switchV.addTarget(self, action: "onChangeSwitch:", forControlEvents: UIControlEvents.ValueChanged)

The problem is figuring out which switch was selected. I know of 3 methods. Each is unsatisfying somewhow.

1. I can use tags:

switchV.tag = indexPath.row

But this sucks if you have sections (and I do), because I need to parse it into and out of a two-number section/row format.

2. I could use the data model and store the switch view on the data item that the cell is drawing:

dataItem.switch.addTarget(self, action: "onChangeSwitch:", forControlEvents: UIControlEvents.ValueChanged)
cell.accessoryView = dataItem.switch

I can then identify which switch was selected by looping over my data set and doing an identity match with sender. This is a lot of looping, and I don't want to put views in my data model.

3. Then there's this method that uses the coordinate of the switch to find the row. Stateless-ish, involves no string parsing or data model muddying, but coordinates, rly? Can I trust it?

tableView.indexPathForRowAtPoint(
  sender.convertPoint(CGPointZero, toView: tableView)
)

Is there a better way to get the indexPath of the UISwitch that is selected?

Community
  • 1
  • 1
SimplGy
  • 20,079
  • 15
  • 107
  • 144

2 Answers2

4

Method #3 is pretty good in my opinion. However if you want it to be really clean here's what I would do .

  • Declare a custom TableviewCell say CustomTableViewCell and have a delegate protocol called CustomCellDelegate. Here the delegate gets informed like so :

     -(void)switchChanged:(UISwitch*)switch inCell:(CustomTableViewCell*)cell
    
  • In cellForRowAtIndexPath set your view controller as the delegate of the cell.

  • Add the switch to to your custom cell and make the cell as the target and implement the switch's action method. Inside the action method call the delegate :

    -(void)switchChanged:(id)sender {
        if(self.delegate && [self.delegate respondsToSelector:@selector(switchChanged:inCell:])) {
            [self.delegate switchChanged:sender inCell:self];
    }
    
  • Now in your viewController use the passed in cell in the delegate method to calculate the index path :

     -(void)switchChanged:(id)sender inCell:(CustomTableViewCell*)cell {
        NSIndexPath *path = [self.tableview indexPathForCell:cell];
     }
    

Its a bit of work but if you want to do it the proper way , you can .

Samhan Salahuddin
  • 2,140
  • 1
  • 17
  • 24
1

Another option is to use an hash which maintains the switch -> data link

var switchToData=[UISwitch:yourData]()

in cellForRowAtIndexPath:

switchToData[newSwitch]=myData

in onChangeSwitch

dataChanged=switchToData[switchChanged]

The hash will be quite small, the same size of the visible switch....

tomsoft
  • 4,448
  • 5
  • 28
  • 35