iosswiftuicontroltarget-action

Prevent parent UIControl from responding to touchDown events


I am creating a reusable MetaControl that consists of a few sub-controls (see pic). It inherits from UIControl, and contains 2 simple UIButtons and a custom slider I created. The CustomSlider also inherits from UIControl.

enter image description here

In the MetaControl's initializer, I add some target actions that receive events from the sub-controls to inform the MetaControl of changes.

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)
    }
}

and then later I put the selector:

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

The problem I'm having is with the sliderTouched() event. This event gets fired twice whenever I touch the slider.

My question is, how can I prevent the MetaControl itself from responding to events, while still allowing my CustomSlider to send its actions?

I used 2 ways to confirm that it was the MetaControl itself which triggered the extra event:

Interestingly, the UIButtons do not cause this same problem. Pressing the UIButton does not cause two events to be fired. How can I achieve this same thing?

P.S. The way I am causing the events to be sent from the CustomSlider is through a custom UIPanGestureRecognizer which is embedded into the CustomSlider's own initializer.

I used this as a guideline: https://www.raywenderlich.com/82058/custom-control-tutorial-ios-swift-reusable-knob

P.P.S I hope I'm not going about this the wrong way-- embedding all these sub-controls into a MetaControl that then itself inherits from UIControl. The MetaControl itself never responds to touch events-- only the subcontrols. I'm using the MetaControl mostly as a container to manage the shared state, provide structure to the layout, and to make the control re-usable. Eventually, I need many of them.

enter image description here


Solution

  • The answer was to make sure to also override touchesBegan in the slider.

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    }