Stephen
Stephen

Reputation: 3465

Swift UISwitch event before value changes

I just wanted to check few conditions before the UISwitch value changes. If conditions are met, then only allow it to change. In documentation, only valueChanged event is available. Which is called after the value is changed.

Any other alternatives ?

Upvotes: 0

Views: 2375

Answers (2)

esesmuedgars
esesmuedgars

Reputation: 138

As @xoudini suggested in the comments under his answer, the desired behaviour can be achieved by subclassing a UISwitch class and overriding it's hitTest(_:with:) and touchesBegan(_:with:) methods.

You override hitTest(_:with:) to stop event propagation to the subviews of your subclass, that way actual switch view the responds to gestures is never reached. And override touchesBegan(_:with:) to provide callback to act when switch has been tapped.

NB! You lose some native behaviours such as long-press and pan gesture interactions. Current solution limits switch to only tap gestures (however, the state change is still animated).

final class Switch: UISwitch {
    
    var onTouchesBegun: ((UISwitch) -> Void)?

    override func hitTest(
        _ point: CGPoint,
        with event: UIEvent?
    ) -> UIView? {
        guard self.point(inside: point, with: event) else {
            return nil
        }

        guard isUserInteractionEnabled else {
            return nil
        }
        
        return self
    }
    
    override func touchesBegan(
        _ touches: Set<UITouch>,
        with event: UIEvent?
    ) {
        super.touchesBegan(touches, with: event)
        
        onTouchesBegun?(self)
    }
}

After you instantiate your subclass, set callback from which you manually, programmatically change the state of the switch.

let isOn: Bool
let animated: Bool

let switch: Switch = .init()
switch.onTouchesBegun = { [isOn, animated] switch in
    // Execute code that determines if/when switch should change state
    
    switch.setOn(isOn, animated: animated)
}

Upvotes: 0

xoudini
xoudini

Reputation: 7031

You have at least two alternatives:

  1. Make a check at some point before the switch would be toggled and disable it.
  2. Let the switch be toggled and in your valueChanged method perform the check before proceeding. If the conditions are not met, use the setOn() method to reset the UISwitch to the previous state.

Upvotes: 0

Related Questions