1

I'm trying to toggle an UISwitch through an objc function, however the switch is not recognizing the UITapGestureRecognizer I implemented.

My Controller

StatusAvailabilityCell

// MARK: - Properties

lazy var toggle: UISwitch = {
    let toggle = UISwitch()
    toggle.isOn = false
    toggle.isEnabled = true
    toggle.onTintColor = .darkPurpleTint
    return toggle
}()

// MARK: - Lifecycle

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    
    configureUI()
    handleToggle()
}

// MARK: - Selectors

@objc func toggleSwitch(_ sender: UISwitch) {
    if sender.isOn == true {
        sender.tintColor = .darkPurpleTint
        sender.setOn(true, animated: true)
    } else {
        sender.tintColor = .white
        sender.setOn(false, animated: true)
    }
}

// MARK: - Helper Functions

fileprivate func handleToggle() {
    
    let tap = UITapGestureRecognizer(target: self, action: #selector(toggleSwitch(_:)))
    tap.numberOfTapsRequired = 1
    toggle.addGestureRecognizer(tap)
    
}

StatusAvailabilityController

// MARK: - UITableViewDataSource

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: CellIdentifiers.StatusAvailabilityCell, for: indexPath) as! StatusAvailabilityCell
    cell.selectionStyle = .none
    cell.separatorInset = UIEdgeInsets.init(top: 0, left: cell.bounds.size.width, bottom: 0, right: 0)
    return cell
}

I have tried to do an addTarget implementation to the UISwitch instead of an UITapGestureRecognizer. I also tried to implement setOn() but it still isn't switching on and off. Thank you in advance.

1 Answers1

1

The key issue here is that you are attempting to use your own tap gesture to toggle the switch. That's unnecessary. A switch already handles touch events to toggle itself.

You need to add a target/action handler to the switch to be notified when it is changed. You then handle the updated state as needed.

Here's an updated version of your posted code:

lazy var toggle: UISwitch = {
    let toggle = UISwitch()
    toggle.isOn = false
    toggle.isEnabled = true
    toggle.onTintColor = .darkPurpleTint
    toggle.addTarget(self, action: #selector(toggleSwitch), for: .valueChanged)

    return toggle
}()

// MARK: - Lifecycle

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    
    configureUI()
}

// MARK: - Selectors

@objc func toggleSwitch(_ sender: UISwitch) {
    if sender.isOn {
        sender.tintColor = .darkPurpleTint
    } else {
        sender.tintColor = .white
    }

    // Or just the following:
    // sender.tintColor = sender.isOn ? .darkPurpleTint : .white
}

Delete your handleToggle function.

And I'm not sure why you are changing the switch's tint colors when it changes. You already set the onTintColor when you created it.

HangarRash
  • 7,314
  • 5
  • 5
  • 32