В Свифт 3 Я мог бы представить как минимум 2 решения следующим образом. Для особого случая я также опубликовал третье решение, в котором выбранный сегмент работает как кнопка переключения.
Решение 1:
Подсказка: это решение работает только с мгновенными управляющими сегментами! Если вам нужно решение для стационарного контроля, выберите Решение 2
Идея состоит в том, чтобы зарегистрировать второе событие, которое запускается при внутренней обработке:
// this solution works only for momentary segment control:
class Solution1ViewController : UIViewController {
var current:Int = UISegmentedControlNoSegment
@IBOutlet weak var mySegmentedControl: UISegmentedControl! {
didSet {
guard mySegmentedControl != nil else { return }
self.mySegmentedControl!.addTarget(
self,
action:#selector(changeSelection(sender:)),
for: .valueChanged)
self.mySegmentedControl!.addTarget(
self,
action:#selector(changeSelection(sender:)),
for: .touchUpInside)
}
}
func changeSelection(sender: UISegmentedControl) {
if current == sender.selectedSegmentIndex {
// user hit the same button again!
print("user hit the same button again!")
}
else {
current = sender.selectedSegmentIndex
// user selected a new index
print("user selected a new index")
}
}
}
Решение 2:
Другой способ - переопределить сенсорные функции в UISegmentedControl
и запустить valueChanged
, даже если индекс сегмента не изменился. Поэтому вы можете переопределить UISegmentedControl
следующим образом:
// override UISegmentControl to fire event on second hit:
class Solution2SegmentControl : UISegmentedControl
{
private var current:Int = UISegmentedControlNoSegment
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
current = self.selectedSegmentIndex
super.touchesBegan(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
if current == self.selectedSegmentIndex {
self.sendActions(for: .valueChanged)
}
}
}
// solution2 works with stationary (default) segment controls
class Solution2ViewController : UIViewController {
var current:Int = UISegmentedControlNoSegment
@IBOutlet weak var mySegmentedControl: UISegmentedControl! {
didSet {
guard mySegmentedControl != nil else { return }
self.mySegmentedControl!.addTarget(
self,
action:#selector(changeSelection(sender:)),
for: .valueChanged)
}
}
func changeSelection(sender: UISegmentedControl) {
if current == sender.selectedSegmentIndex {
// user hit the same button again!
print("user hit the same button again!")
}
else {
current = sender.selectedSegmentIndex
// user selected a new index
print("user selected a new index")
}
}
}
Решение 3:
Если ваш подход состоял в том, чтобы выбранный сегмент был кнопкой переключения, можно было бы изменить Решение 2, чтобы очистить код следующим образом:
class MyToggleSegmentControl : UISegmentedControl {
/// you could enable or disable the toggle behaviour here
var shouldToggle:Bool = true
private var current:Int = UISegmentedControlNoSegment
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
current = self.selectedSegmentIndex
super.touchesBegan(touches, with: event)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesEnded(touches, with: event)
if shouldToggle, current == self.selectedSegmentIndex {
self.selectedSegmentIndex = UISegmentedControlNoSegment
}
}
}
Теперь мы можем очистить функцию changeSelection
следующим образом:
func changeSelection(sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case UISegmentedControlNoSegment:
print("none")
default:
print("selected: \(sender.selectedSegmentIndex)")
}
}