Запретить родительскому UIControl отвечать на события touchDown

Я создаю многоразовую MetaControl это состоит из нескольких субэлементов управления (см. рис.). Наследуется от UIControl и содержит 2 простых UIButtons и пользовательский слайдер, который я создал. CustomSlider также наследует от UIControl,

введите описание изображения здесь

в MetaControl инициализатор, я добавляю некоторые целевые действия, которые получают события от субэлементов управления, чтобы информировать MetaControl изменений.

class MetaControl: UIControl {
    public override init(frame: CGRect) {
        self.slider.addTarget(self, action: #selector(sliderValueChanged), for: .valueChanged)
        self.slider.addTarget(self, action: #selector(sliderTouched), for: .touchDown)
        self.button1.addTarget(self, action: #selector(button1Pressed), for: .touchDown)
        self.button2.addTarget(self, action: #selector(button2Pressed), for: .touchDown)
    }
}

а потом я поставил селектор:

@objc private func sliderTouched() {
     print("The slider was touched")
}

У меня проблема с sliderTouched() событие. Это событие запускается дважды, когда я прикасаюсь к ползунку.

  • Первый раз, кажется, отправлено с MetaControl сам.
  • Второй раз - правильное событие, передаваемое из CustomSlider сам.

У меня вопрос, как я могу предотвратить MetaControl сам реагировать на события, в то же время позволяя моим CustomSlider отправить свои действия?

Я использовал 2 способа, чтобы подтвердить, что это было MetaControl Сам, который вызвал дополнительное событие:

  • Закомментировал действие кода отправки в CustomSlider, Даже без этой строки кода, sliderTouched() еще называется:

    class CustomSlider: UIControl {
         var isTouched = false {
            didSet {
                //sendActions(for: .touchDown)
            } 
        }
    }
    
  • Заменил .touchDown действие с .applicationReserved, Так как я больше не использую .touchDown, MetaControl "s .touchDown событие никогда не называется.

    class CustomSlider: UIControl {
        var isTouched = false {
            didSet {
                sendActions(for: .applicationReserved)
            } 
        }
    }
    

Интересно, что UIButtons не вызывайте этой же проблемы. Нажатие UIButton не вызывает двух событий для запуска. Как я могу достичь этого же?

PS То, как я вызываю события от CustomSlider через обычай UIPanGestureRecognizer который встроен в CustomSlider собственный инициализатор.

Я использовал это в качестве руководства: https://www.raywenderlich.com/82058/custom-control-tutorial-ios-swift-reusable-knob

PPS Я надеюсь, что я не пойду неправильно, включив все эти элементы управления в MetaControl что тогда само наследует от UIControl, MetaControl сам никогда не реагирует на сенсорные события - только субконтроли. Я использую MetaControl в основном в качестве контейнера для управления общим состоянием, обеспечения структуры макета и повторного использования элемента управления. В конце концов, мне нужно много из них.

введите описание изображения здесь

1 ответ

Решение

Ответ состоял в том, чтобы убедиться, что также переопределить touchesBegan в слайдере.

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
}
Другие вопросы по тегам