ilan
ilan

Reputation: 4462

TapGestureRecogniser not getting called when a subview

I have a view A that handles UITapGestureRecogniser. When it's on its own everything works great.

I have another View B that holds six of the View A objects. When I add View B to my ViewController the UITapGestureRecogniser stops working.

I have isUserInteractionEnabled = true on all the views.

Can anyone spot why it's not working?

How can I check if the tapGestures are being activated upon touch?

Thanks

Note: The ViewController doesn't have any UIGestureRecognisers on it


SingleView

class QTSingleSelectionView: UIView {

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

    override init(frame: CGRect) {
        super.init(frame: frame)
        initialize()
    }

    fileprivate func initialize() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(onTapListener))
        addGestureRecognizer(tap)
    }

    func onTapListener() {
        print("tap")
        _isSelected.toggle()
        setSelection(isSelected: _isSelected, animated: true)
    }

}

Multiple views

class QTMutipleChoiceQuestionSelector: UIView {

    var selectors: [QTSingleSelectionView] = []

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

    override init(frame: CGRect) {
        super.init(frame: frame)
        initialize()
    }

    fileprivate func initialize() {

        for selector in selectors {
           selector.removeFromSuperview()
        }

        selectors.removeAll()

        guard let dataSource = dataSource else { return }

        let count = dataSource.numberOfAnswers(self)

        for index in 0..<count {
            let selector = QTSingleSelectionView()

            selector.frame = CGRect(x: 0, y: topMargin + heightOfSelector*CGFloat(index), width: frame.width, height: heightOfSelector)
            selector.text = dataSource.mutipleChoiceQuestionSelector(self, textForAnswerAtIndex: index)
            selector.selected = dataSource.mutipleChoiceQuestionSelector(self, isItemSelectedAtIndex: index)
            selector.isUserInteractionEnabled = true
            addSubview(selector)
        }
    }

}

ViewController

lazy var multipleChoiceView: QTMutipleChoiceQuestionSelector = {
    let selector = QTMutipleChoiceQuestionSelector()
    selector.dataSource = self
    selector.isUserInteractionEnabled = true
    return selector
}()

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.
    view.addSubview(multipleChoiceView)

}

Upvotes: 0

Views: 90

Answers (2)

Yun CHEN
Yun CHEN

Reputation: 6648

I have tested your code. The problem is in line:

let selector = QTMutipleChoiceQuestionSelector() //Wrong!

This line initializes the view with frame (0,0,0,0), that means it cannot receive any touch event, even if you could see it. The solution is giving the view a size to receive events:

let selector = QTMutipleChoiceQuestionSelector(frame: CGRect(x: 0.0, y: 0.0, width: self.view.frame.width, height: self.view.frame.height))

Upvotes: 1

Rhm Akbari
Rhm Akbari

Reputation: 360

Try This - Instead of :

for index in 0..<count {
        let selector = QTSingleSelectionView()

        selector.frame = CGRect(x: 0, y: topMargin + heightOfSelector*CGFloat(index), width: frame.width, height: heightOfSelector)
        selector.text = dataSource.mutipleChoiceQuestionSelector(self, textForAnswerAtIndex: index)
        selector.selected = dataSource.mutipleChoiceQuestionSelector(self, isItemSelectedAtIndex: index)
        selector.isUserInteractionEnabled = true
        addSubview(selector)
    }

You should use :

for index in 0..<count {
    let aFrame: CGRect = CGRect(x: 0, y: topMargin + heightOfSelector*CGFloat(index), width: frame.width, height: heightOfSelector)
    let selector = QTSingleSelectionView(frame: aFrame)

    selector.text = dataSource.mutipleChoiceQuestionSelector(self, textForAnswerAtIndex: index)
    selector.selected = dataSource.mutipleChoiceQuestionSelector(self, isItemSelectedAtIndex: index)
    selector.isUserInteractionEnabled = true
    addSubview(selector)
}

This will call the appropriate initializer which is init(frame: CGRect) which has the initializer() inside it. But right now your code call's default init() function of the UIView which does not have your custom initialize.

Upvotes: 0

Related Questions