问题
I have a UISwitch in a tableviewcontroller, and when the switch is toggled I want it to change the value of a boolean variable in an array I created inside the view controller, that the cell is related to. Kind of like the Stock Alarm App on IOS, where each cell has a UISwitch, and toggling the switch will turn off each individual alarm. So with the UISwitch, with its selector code, this is inside the cellForRowAtIndexPath method
//switch
let lightSwitch = UISwitch(frame: CGRectZero) as UISwitch
lightSwitch.on = false
lightSwitch.addTarget(self, action: #selector(switchTriggered), forControlEvents: .ValueChanged)
//lightSwitch.addTarget(self, action: "switchTriggered", forControlEvents: .ValueChanged )
cell.accessoryView = lightSwitch
I want it to do this
func switchTriggered(a: Int) {
changeValueOfArray = array[indexPath.row]
}
I don't have the code written for that part yet, but my question is, How can i let the switchTriggered function see the indexPath.row value, without passing it as an argument to the function because I can't because its a selector?
回答1:
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
}
}
回答2:
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:
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
nameof aRoomand a boolean reflecting whether the light is on:struct Room { var name: String var lightsOn: Bool }Then the table view controller would have an array of those:
var rooms: [Room]!I'd define a
UITableViewCellsubclass 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
UITableViewCellsubclass and hook up the@IBOutletreferences as well as the@IBActionfor the changing of the value for the switch.I'd then have the
UITableViewDataSourcemethods populate the cell on the basis of theRoomproperties: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 }Note, the above
cellForRowAtIndexPathalso specifies itself as thedelegatefor the cell, so we'd want to implement theRoomLightDelegateprotocol 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:).
回答3:
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
来源:https://stackoverflow.com/questions/39566065/uiswitch-in-accessory-view-of-a-tableviewcell-passing-a-parameter-with-the-sele