Search code examples
swiftuikitcelluitapgesturerecognizerstackview

Tap on the StackView elements nothing happens in simulator


I encountered a problem, it doesn't work. When I assign a tap to a StackView element and tap through the simulator, nothing happens. Please tell me in detail what the problem is, what I misunderstand.

I created UITableView which contains CustomCell. CustomCell contains ViewWrap and ViewWrap contains StackView with View as elements. I assign a UITapGestureRecognizer to a View that contains a StackView.

P.S. In the future, I will change the code and create two user classes (there will be different functions for taps) for all views that are included in StackView.

class CustomCell: UITableViewCell {
    static let ident = "cell"

    let viewWrapp: UIView = {
       let vwWrapp = UIView()
       vwWrapp.translatesAutoresizingMaskIntoConstraints = false
       return vwWrapp
    }()
    
    let stackView: UIStackView = {
       var st = UIStackView()
       st.translatesAutoresizingMaskIntoConstraints = false
       st.axis = .horizontal
       st.distribution = .fillEqually
       st.alignment = .bottom
       st.spacing = 0
       st.isUserInteractionEnabled = true
        
       return st
    }()
    
    var view11: UILabel = {
        let vw = UILabel()
        vw.translatesAutoresizingMaskIntoConstraints = false
        vw.text = "4"
        vw.font = UIFont(name: "LittleBird", size: 47)
        vw.textAlignment = .center
        
        vw.isUserInteractionEnabled = true
        let tapGesture = UITapGestureRecognizer(target: CustomCell.self, action: #selector(tabTab))
        tapGesture.numberOfTapsRequired = 1
        tapGesture.numberOfTouchesRequired = 1
        vw.addGestureRecognizer(tapGesture)
        
        return vw
    }()
        
    var view22: UILabel = {
        let vw = UILabel()
        vw.translatesAutoresizingMaskIntoConstraints = false
        vw.text = "+"
        vw.font = UIFont(name: "LittleBird", size: 30)
        vw.textAlignment = .center
        vw.layer.borderColor = CGColor(red: 1, green: 0, blue: 0, alpha: 1)
        vw.isUserInteractionEnabled = true
        
        let tapGesture = UITapGestureRecognizer(target: CustomCell.self, action: #selector(tabTab))
        tapGesture.numberOfTapsRequired = 1
        tapGesture.numberOfTouchesRequired = 1
        vw.addGestureRecognizer(tapGesture)

        return vw
    }()
    
// ...   ...
// ...   ...
// ...   ...

    var view77: UILabel = {
        let vw = UILabel()
        vw.translatesAutoresizingMaskIntoConstraints = false
        vw.text = "4"
        vw.font = UIFont(name: "LittleBird", size: 47)
        vw.textAlignment = .center
        vw.isUserInteractionEnabled = true
        
        let tapGesture = UITapGestureRecognizer(target: CustomCell.self, action: #selector(tabTab))
        tapGesture.numberOfTapsRequired = 1
        tapGesture.numberOfTouchesRequired = 1
        vw.addGestureRecognizer(tapGesture)
        
        return vw
    }()
    
    var view88: UILabel = {
        let vw = UILabel()
        vw.translatesAutoresizingMaskIntoConstraints = false
        vw.text = "="
        vw.font = UIFont(name: "LittleBird", size: 30)
        vw.textAlignment = .center
        
        return vw
    }()
    
    var view99: UILabel = {
        let vw = UILabel()
        vw.translatesAutoresizingMaskIntoConstraints = false
        vw.textAlignment = .center
        
        vw.font = UIFont(name: "LittleBird", size: 47)

        vw.layoutIfNeeded()
        
        vw.numberOfLines = 0
        return vw
    }()
    
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        isUserInteractionEnabled = true
        
        contentView.addSubview(viewWrapp)
        
        stackView.addArrangedSubview(view11)
        stackView.addArrangedSubview(view22)
        stackView.addArrangedSubview(view33)
        stackView.addArrangedSubview(view44)
        stackView.addArrangedSubview(view55)
        stackView.addArrangedSubview(view66)
        stackView.addArrangedSubview(view77)
        stackView.addArrangedSubview(view88)
        stackView.addArrangedSubview(view99)
        
        viewWrapp.addSubview(stackView)
        
        setConstraints()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        isUserInteractionEnabled = true
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
    
    @objc func tabTab(){
        print("Tab Tab")
    }
    
    func setConstraints() {
        NSLayoutConstraint.activate([
            viewWrapp.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            viewWrapp.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
            viewWrapp.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
            
            stackView.leadingAnchor.constraint(equalTo: viewWrapp.leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: viewWrapp.trailingAnchor),
            stackView.heightAnchor.constraint(equalToConstant: 60)
        ])
    }
}

I tried to assign a UITapGestureRecognizer to the view that is in the StackView, but there was no response to the tap. Also added isUserInteractionEnabled = true in:

  • View what in StackView
  • StackView
  • override init(style: UITableViewCell.CellStyle
  • override func awakeFromNib()
  • tabView.delaysContentTouches = false

Solution

  • To summarise your problem, you are trying to add a tap gesture in a view (in your case it's a UILabel) but it's not working.

    There is a similar problem which you can check How to set a click event on a UIStackview

    To solve your problem, one of the many solutions is to make all of the UILabel var to lazy var and modify UITapGestureRecognizer target parameter CustomCell.self to self.

    Apart from the solution, You have added translatesAutoresizingMaskIntoConstraints to every child UILabel which is not required since you are setting NSLayoutConstraint only in viewWrapp and stackView.

    I have added a working solution from your provided code snippet.

    class CustomCell: UITableViewCell {
        
        static let ident = "cell"
        
        lazy var viewWrapp: UIView = {
            let vwWrapp = UIView()
            vwWrapp.translatesAutoresizingMaskIntoConstraints = false
            return vwWrapp
        }()
        
        lazy var stackView: UIStackView = {
            var st = UIStackView()
            st.translatesAutoresizingMaskIntoConstraints = false
            st.axis = .horizontal
            st.distribution = .fillEqually
            st.alignment = .bottom
            st.spacing = 0
            st.isUserInteractionEnabled = true
        
            return st
        }()
        
        lazy var view11: UILabel = {
            let vw = UILabel()
            vw.text = "4"
            vw.font = UIFont(name: "LittleBird", size: 47)
            vw.textAlignment = .center
            
            vw.isUserInteractionEnabled = true
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tabTab))
            tapGesture.numberOfTapsRequired = 1
            tapGesture.numberOfTouchesRequired = 1
            vw.addGestureRecognizer(tapGesture)
            
            return vw
        }()
        
        lazy var view22: UILabel = {
            let vw = UILabel()
            vw.text = "+"
            vw.font = UIFont(name: "LittleBird", size: 30)
            vw.textAlignment = .center
            vw.layer.borderColor = CGColor(red: 1, green: 0, blue: 0, alpha: 1)
            vw.isUserInteractionEnabled = true
            
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tabTab))
            tapGesture.numberOfTapsRequired = 1
            tapGesture.numberOfTouchesRequired = 1
            vw.addGestureRecognizer(tapGesture)
            
            return vw
        }()
        
        lazy var view77: UILabel = {
            let vw = UILabel()
            vw.text = "4"
            vw.font = UIFont(name: "LittleBird", size: 47)
            vw.textAlignment = .center
            vw.isUserInteractionEnabled = true
            
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tabTab))
            tapGesture.numberOfTapsRequired = 1
            tapGesture.numberOfTouchesRequired = 1
            vw.addGestureRecognizer(tapGesture)
            
            return vw
        }()
        
        lazy var view88: UILabel = {
            let vw = UILabel()
            vw.text = "="
            vw.font = UIFont(name: "LittleBird", size: 30)
            vw.textAlignment = .center
            
            return vw
        }()
        
        
        override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
            stackView.addArrangedSubview(view11)
            stackView.addArrangedSubview(view22)
            stackView.addArrangedSubview(view77)
            stackView.addArrangedSubview(view88)
            
            
            contentView.addSubview(viewWrapp)
            viewWrapp.addSubview(stackView)
            
            setConstraints()
            
        }
        
        func setConstraints() {
            NSLayoutConstraint.activate([
                viewWrapp.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
                viewWrapp.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
                viewWrapp.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
                
                stackView.topAnchor.constraint(equalTo: viewWrapp.topAnchor),
                stackView.bottomAnchor.constraint(equalTo: viewWrapp.bottomAnchor),
                stackView.leadingAnchor.constraint(equalTo: viewWrapp.leadingAnchor),
                stackView.trailingAnchor.constraint(equalTo: viewWrapp.trailingAnchor)
            ])
        }
        
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
        
        @objc func tabTab(){
            print("Tab Tab")
        }
    }
    

    Apart from my solution, this problem can solved in many ways.

    For example: Adding buttons mentioned by @HangarRash comments.