That's weird: I just set up a new Single-View iOS Project and put a TableView into the Main.storyboard. In this TableView I put a TableViewCell and into this Cell, I put an UILabel and an UISwitch. For this TableViewCell I created a CocoaTouchClass MyTableViewCell and set this for the TableViewCell's Class in Interfacebuilder. I connected Outlets for the UILabel and UISwitch to MyTableViewCell, as well as an action for the switch. Also I connected the TableView's dataSource and delegate to the ViewController.
So, as I think, basic stuff for setting up a table.
My ViewController looks like this:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableData = [[String: Bool]]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for index in 1...40 {
self.tableData.append([String(index): index%2 == 0])
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.tableData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "mycell", for: indexPath) as! MyTableViewCell
let object = tableData[indexPath.row].first!
cell.myLabel.text = object.key
cell.mySwitch.setOn(object.value, animated: false)
return cell
}
}
So, I populate the Table with some Rows of Data and switch every second UISwitch to on.
The MyTableViewCell-Class is nothing special as well:
class MyTableViewCell: UITableViewCell {
@IBOutlet weak var myLabel: UILabel!
@IBOutlet weak var mySwitch: UISwitch!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
@IBAction func switched(_ sender: UISwitch) {
print("Switched: \(sender.isOn)")
}
}
Ok, fire up the iOS-Simulator and I see the Table as expected. 40 Table-Lines don't fit on one screen, so the TableView makes itself scrollable.
Now: when I change the state of one UISwitch, and drag the TableView so the changed UISwitch gets out of view and then drag the TableView so the changed UISwitch gets visible again, it is changed back to its initial state. The Switch-event gets fired like it should.
So, what am I doing wrong? Am I missing something?
I recorded a 4-seconds-Screencast to demonstrate, what's going on: http://b-bereich.de/download/swiftSwitch.mov
I think you need to have your IBAction change the Bool each time you flip the switch. Currently the switch changes the UI but not the underlying Bool so the
cellForRowAt
method uses the currently saved value when the cell scrolls back on screen.TableViewCells are reused.
That means you need to keep track of the data you are using to fill the content of the cells. If the cell content changes - such as when you tap a Switch in the cell - you need to update your datasource. When you scroll, and that row is displayed again, your data will know how to set the state of the Switch.
Here is a simple example:
Add function prepareForReuse() in your custom cell class and set switch state to off by default. -: