Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read the changes in UISwitch in a custom UITableViewCell

Although I've found similar questions asked, I'm not able to comprehend the answers for it.

How would we read the changes in UISwitch or for that matter any element while in a UITableViewCell? Tried using a protocol, but the custom cell class complains about no initialisers. Used, a delegate, which seems to not conform to the view controller.

protocol SwitchTableViewCellDelegate {
    func didChangeSwitchValue(value: Bool)
}

class SwitchTableViewCell: UITableViewCell {

var delegate: SwitchTableViewCellDelegate
var value: Bool =  true

@IBOutlet weak var switchCellLabel: UILabel!
@IBOutlet weak var switchCellSwitch: UISwitch!
@IBAction func changedSwitchValue(sender: UISwitch) {
    self.value = sender.on
    delegate.didChangeSwitchValue(value)
}

In cellForRowAtIndexPath,

let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell
                cell.delegate = self
                cell.switchCellLabel?.text = "Show Cloud Music"
                cell.switchCellSwitch.on = userDefaults.boolForKey(cloudMusicKey)

Any suggestions, on how to implement this?

like image 706
Shyam Avatar asked Mar 11 '23 23:03

Shyam


2 Answers

I would suggest using a Swift closure for this. Use the following code in your cell class:

class SwitchTableViewCell: UITableViewCell {

var callback: ((switch: UISwitch) -> Void)?
var value: Bool =  true

@IBOutlet weak var switchCellLabel: UILabel!
@IBOutlet weak var switchCellSwitch: UISwitch!
@IBAction func changedSwitchValue(sender: UISwitch) {
    self.value = sender.on
    callback?(switch: sender)
}

Then this code in your cellForRowAtIndexPath:

let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell
cell.callback = { (switch) -> Void in 
    // DO stuff here.
}
cell.switchCellLabel?.text = "Show Cloud Music"
cell.switchCellSwitch.on = userDefaults.boolForKey(cloudMusicKey)
like image 79
Jacob King Avatar answered Apr 09 '23 00:04

Jacob King


Firstly, since there can be many cells sharing the same delegate, the delegate should know which cell calls it. Hence, your protocol method should provide the cell itself, not just its switch value. In fact, we can omit the switch value parameter since it can be queried from the cell.

protocol SwitchTableViewCellDelegate {
    func switchTableViewCellDidChangeSwitchValue(cell: SwitchTableViewCell)
}

In your delegate's implementation of the protocol method, you can access the switch value like this:

func switchTableViewCellDidChangeSwitchValue(cell: SwitchTableViewCell) {
    let switchValue = cell.value
}

Secondly, the delegate property can be nil so its type must be an Optional.

var delegate: SwitchTableViewCellDelegate?

To call the delegate when value changes:

delegate?.switchTableViewCellDidChangeSwitchValue(self)
like image 20
Thanh Pham Avatar answered Apr 09 '23 00:04

Thanh Pham