UISwitch in accessory view of a tableviewcell, passing a parameter with the selector to have selector function see the indexpath.row?

六月ゝ 毕业季﹏ 提交于 2019-11-28 14:06:18
let lightSwitch = UISwitch(frame: CGRectZero) as UISwitch
    lightSwitch.on = false
    lightSwitch.addTarget(self, action: #selector(switchTriggered), forControlEvents: .ValueChanged)
    lightSwitch.tag = indexpath.row
    cell.accessoryView = lightSwitch

Let save your boolean value in Array

    func switchTriggered(sender: UISwitch) {
      sender.on ? array[sender.tag]=1 : array[sender.tag]=0
     }
}

The basic idea is that you can capture the cell for which the switch was flipped and then use tableView.indexPath(for:) to translate that UITableViewCell reference into a NSIndexPath, and you can use its row to identify which row in your model structure needs to be updated.

The constituent elements of this consist of:

  1. Create a model object that captures the information to be shown in the table view. For example, let's imagine that every cell contains a name of a Room and a boolean reflecting whether the light is on:

    struct Room {
        var name: String
        var lightsOn: Bool
    }
    
  2. Then the table view controller would have an array of those:

    var rooms: [Room]!
    
  3. I'd define a UITableViewCell subclass with outlets for the label and the switch. I'd also hook up the "value changed" for the light switch to a method in that cell. I'd also set up a protocol for the cell to inform its table view controller that the light switch was flipped:

    protocol RoomLightDelegate: class {
        func didFlipSwitch(for cell: UITableViewCell, value: Bool)
    }
    
    class RoomCell: UITableViewCell {
    
        weak var delegate: RoomLightDelegate?
    
        @IBOutlet weak var roomNameLabel: UILabel!
        @IBOutlet weak var lightSwitch: UISwitch!
    
        @IBAction func didChangeValue(_ sender: UISwitch) {
            delegate?.didFlipSwitch(for: self, value: sender.isOn)
        }
    
    }
    

    I'd obviously set the base class for the cell prototype to be this UITableViewCell subclass and hook up the @IBOutlet references as well as the @IBAction for the changing of the value for the switch.

  4. I'd then have the UITableViewDataSource methods populate the cell on the basis of the Room properties:

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return rooms.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "SwitchCell", for: indexPath) as! RoomCell
    
        let room = rooms[indexPath.row]
    
        cell.roomNameLabel.text = room.name
        cell.lightSwitch.setOn(room.lightsOn, animated: false)
        cell.delegate = self
    
        return cell
    }
    
  5. Note, the above cellForRowAtIndexPath also specifies itself as the delegate for the cell, so we'd want to implement the RoomLightDelegate protocol to update our model when the light switch is flipped:

    extension ViewController: RoomLightDelegate {
    
        func didFlipSwitch(for cell: UITableViewCell, value: Bool) {
            if let indexPath = tableView.indexPath(for: cell) {
                rooms[indexPath.row].lightsOn = value
            }
        }
    
    }
    

Now, I don't want you to worry about the details of the above. Instead, try to capture some of the basic ideas:

Bottom line, to your immediate question, once you know which cell was was updated, you can inquire with the UITableView to determine what NSIndexPath that UITableViewCell reference corresponds to, using tableView.indexPath(for:).

Swift 3 Update:

let lightSwitch = UISwitch(frame: CGRect.zero) as UISwitch
lightSwitch.isOn = false
lightSwitch.addTarget(self, action: #selector(switchTriggered), for: .valueChanged)
lightSwitch.tag = indexPath.row
cell?.accessoryView = lightSwitch
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!