Same issue in my app. My app had been working for 9 years but started showing this UISlider bug in iOS 26.
Below used to work previously:
slider.addTarget(self, action: #selector(sliderValueChanged(sender:event:)), for: .valueChanged)
@objc func sliderValueChanged(sender: UISlider, event: UIEvent) {
print("Slider: \(slider.value), \(event)")
label.text = "Value: \(sender.value)"
switch event.allTouches?.first?.phase {
case .began:
print("began")
case .moved:
print("moved")
case .ended:
print("ended")
case .cancelled:
print("cancelled")
default:
break
}
}
But, in iOS 26, the event
being passed is uninitialized and so, event.allTouches
is always nil. So, I am unable to detect what phase
of the event it's in.
Note that changing from UIEvent
to UIControl.Event
is not a solution as it's also just UIControlEvents(rawValue: 0)
, so unable to find what phase
it's in.
I have reported this as a bug: https://feedbackassistant.apple.com/feedback/20727378
EDIT:
For now, the below workaround works:
slider.addTarget(self, action: #selector(sliderEnded(sender:)), for: .touchCancel)
slider.addTarget(self, action: #selector(sliderEnded(sender:)), for: .touchUpInside)
slider.addTarget(self, action: #selector(sliderEnded(sender:)), for: .touchUpOutside)
slider.addTarget(self, action: #selector(sliderChanged(sender:event:)), for: .allTouchEvents)
@objc func sliderCancelled(sender: UISlider) {
sliderPhaseChanged(sender: sender, phase: .cancelled)
}
@objc func sliderEnded(sender: UISlider) {
sliderPhaseChanged(sender: sender, phase: .ended)
}
@objc func sliderChanged(sender: UISlider, event: UIEvent) {
let phase = event.allTouches?.first?.phase
switch phase {
case .began:
sliderPhaseChanged(sender: sender, phase: phase)
case .moved:
sliderPhaseChanged(sender: sender, phase: phase)
default:
break
}
}
func sliderPhaseChanged(sender: UISlider, phase: UITouch.Phase?) {
switch phase {
case .began:
print("began")
case .moved:
print("moved")
case .ended:
print("ended")
case .cancelled:
print("cancelled")
default:
break
}
}