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.
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.
- The first time it seems to be sent from the
MetaControlitself. - The second time is the correct event being passed up from the
CustomSlideritself.
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:
Commented out the action sending code in the
CustomSlider. Even without this line of code,sliderTouched()is still called:class CustomSlider: UIControl { var isTouched = false { didSet { //sendActions(for: .touchDown) } } }Replaced the
.touchDownaction with.applicationReserved. Since I'm no longer using.touchDown, theMetaControl's.touchDownevent is never called.class CustomSlider: UIControl { var isTouched = false { didSet { sendActions(for: .applicationReserved) } } }
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.


The answer was to make sure to also override
touchesBeganin the slider.