UISwitch in a UITableView cell

前端 未结 6 1596
生来不讨喜
生来不讨喜 2020-11-30 21:57

How can I embed a UISwitch on a UITableView cell? Examples can be seen in the settings menu.

My current solution:

6条回答
  •  感动是毒
    2020-11-30 22:36

    This is a more complete solution where turning off and on happens on the view layer (UITableViewCell) and it forwards the events to the tableView delegate through didSelect and didDeselect:

    class CustomCell: UITableViewCell {
        private lazy var switchControl: UISwitch = {
            let s = UISwitch()
            s.addTarget(self, action: #selector(switchValueDidChange(_:)), for: .valueChanged)
            return s
        }()
    
        override func awakeFromNib() {
            self.accessoryView = switchControl
            self.selectionStyle = .none // to show the selection style only on the UISwitch
        }
    
        override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
            (self.accessoryView as? UISwitch)?.isOn = selected
        }
    
        @objc private func switchValueDidChange(_ sender: UISwitch) { // needed to treat switch changes as if the cell was selected/unselected
            guard let tv = self.superview as? UITableView, let ip = tv.indexPath(for: self) else {
                fatalError("Unable to cast self.superview as UITableView or get indexPath")
            }
            setSelected(sender.isOn, animated: true)
            if sender.isOn {
                tv.delegate?.tableView?(tv, didSelectRowAt: ip)
            } else {
                tv.delegate?.tableView?(tv, didDeselectRowAt: ip)
            }
        }
    }
    

    And on your delegate

    
    func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
        return false // to disable interaction since it happens on the switch
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // to make sure it is rendered correctly when dequeuing:
        // stuff
        if isSelected { // stored value to know if the switch is on or off
            tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
        } else {
            tableView.deselectRow(at: indexPath, animated: true)
        }
        // more stuff
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // do your thing when selecting
    }
    
    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        // do your thing when deselecting
    }
    

提交回复
热议问题