slava_slava
slava_slava

Reputation: 666

Why touchesBegan listener not called(Swift 4)?

I created simple button - class Btn: UIControl and then add to parent View. Inside my Btn class I have override func touchesBegan. Why touchesBegan not callend when I tapped to the button? As I think, my Btn extends UIControl and Btn have to call touchesBegan.

My code:

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

//        add my button
        let button = Btn()
        view.addSubview(button)
    }
}

class Btn: UIControl {
    fileprivate let button: UIButton = {
        let swapButton = UIButton()
        let size = CGFloat(50)
        swapButton.frame.size = CGSize(width: size, height: size)
        swapButton.backgroundColor = UIColor.green

        return swapButton
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(button)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        addSubview(button)
    }

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

        //        Why it not called?
        print("test")
    }
}

Upvotes: 0

Views: 995

Answers (1)

Milan Nos&#225;ľ
Milan Nos&#225;ľ

Reputation: 19737

Play around with the following code for playgrounds based on your code, and you will understand what's going on. While your control wants to process the touchesBegan callback, it has an UIButton inside of it, which consumes the event itself. In the example below, the inner button is taking one quarter of the Btn size (red part), if you click on it, the "test" text won't get printed. The rest of the Btn space (green part) does not contain any other view that would consume the touchesBegan, thus clicking there will print "test" text.

I recommend you to take a look at the responder chain.

import PlaygroundSupport
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //        add my button
        let button = Btn(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        view.addSubview(button)
    }
}

class Btn: UIControl {
    fileprivate let button: UIButton = {
        let swapButton = UIButton()
        let size = CGFloat(50)
        swapButton.frame.size = CGSize(width: size, height: size)
        swapButton.backgroundColor = UIColor.green

        return swapButton
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(button)
        self.backgroundColor = .red
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        addSubview(button)
    }

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

        //        Why it not called?
        print("test")
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = ViewController()

Upvotes: 2

Related Questions