Select UITableView's row when tapping on its U

2019-03-11 11:50发布

问题:

This question has been approached here in Objective-C. But I am working in Swift and have a similar question.

Once successfully created, how do I select the UITableView's row when I tap on its UISwitch?

I have a boolean in my model and would like to toggle that boolean based on the switches on/off state.

I have some programmatically created cells that contain switches...

View Controller:

var settings : [SettingItem] = [
        SettingItem(settingName: "Setting 1", switchState: true),
        SettingItem(settingName: "Setting 2", switchState: true)
    ]

override public func tableView(_tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomSettingCell") as! SettingCell

        let settingItem = settings[indexPath.row]
        cell.settingsLabel.text = settingItem.settingName
        cell.settingsSwitch.enabled = settingItem.switchState!

        return cell
    }

based off a model in SettingItem.swift:

class SettingItem: NSObject {

    var settingName : String?
    var switchState : Bool?

    init (settingName: String?, switchState : Bool?) {
        super.init()
        self.settingName = settingName
        self.switchState = switchState
    } 
}

and I have some outlets in SettingCell.swift:

class SettingCell: UITableViewCell {

    @IBOutlet weak var settingsLabel: UILabel!

    @IBOutlet weak var settingsSwitch: UISwitch!


    @IBAction func handledSwitchChange(sender: UISwitch) {
        println("switched")
    }

Which produces this (please ignore the formatting):

回答1:

When I want events to propagate from a cell to the containing controller, I usually define a custom delegate, like this:

protocol SettingCellDelegate : class {
    func didChangeSwitchState(# sender: SettingCell, isOn: Bool)
}

use it in the cell:

class SettingCell: UITableViewCell {
    @IBOutlet weak var settingsLabel: UILabel!
    @IBOutlet weak var settingsSwitch: UISwitch!

    weak var cellDelegate: SettingCellDelegate?

    @IBAction func handledSwitchChange(sender: UISwitch) {
        self.cellDelegate?.didChangeSwitchState(sender: self, isOn:settingsSwitch.on)
        ^^^^
    }
}

implement the protocol in the view controller and set the delegate in the cell:

class ViewController : UITableViewController, SettingCellDelegate {
                                              ^^^^
    override func tableView(_tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("CustomSettingCell") as! SettingCell

        let settingItem = settings[indexPath.row]
        cell.settingsLabel.text = settingItem.settingName
        cell.settingsSwitch.enabled = settingItem.switchState!

        cell.cellDelegate = self
        ^^^^

        return cell
    }

#pragma mark - SettingCellDelegate

    func didChangeSwitchState(#sender: SettingCell, isOn: Bool) {
        let indexPath = self.tableView.indexPathForCell(sender)
        ...
    }
}

When the switch is tapped, the event is propagated to the view controller, with the new status and the cell itself passed as arguments. From the cell you can obtain the index path, and then do whatever you need to, such as selecting the row etc.