UIButton Not Responding to Touch Events

Viewed 111

Problem

I am trying to do everything programmatically, so I have created this ResultController. For some reason, two of my buttons work but the other three don't work. The program doesn't even notice the touch-up event. I have read many posts on this topic but none of the solutions worked for me.

The two buttons that work are the language button and the swap button, which are embedded in a stack view towards the top of the screen. The 3 buttons that don't work are the soundButton, loopButton, and addFlashcardButton on the result card shown in the image below.

Question

What do I need to do such that these buttons respond to touch events?

Here is the code for this viewController, as well as a picture of the result. I will post the important parts and the whole code for reference. The Buttons are laid out in two functions, setupResultsView() and setupScrollView():

Button Instantiation

    var soundButton: UIButton = {
        
        let button = UIButton()
        button.setImage(UIImage(systemName: "speaker.3.fill"), for: .normal)
        button.backgroundColor = .white
        button.tintColor = .black
        button.addTarget(self, action: #selector(soundButtonPressed), for: .touchUpInside)
        return button
        
    }()
    
    var loopButton: UIButton = {
        
        let button = UIButton()
        button.setImage(UIImage(systemName: "repeat"), for: .normal)
        button.backgroundColor = .white
        button.tintColor = .black
        button.addTarget(self, action: #selector(loopButtonPressed), for: .touchUpInside)
        return button
        
    }()
    var addFlashcardButton: UIButton = {
       
        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
        button.setImage(UIImage(systemName: "plus"), for: .normal)
        button.backgroundColor = K.Colors.purple
        button.tintColor = .white
        button.roundCorners(cornerRadius: 15)
        button.addTarget(self, action: #selector(addFlashcardButtonPressed), for: .touchUpInside)
        return button
        
    }()

Selector Functions

@objc func soundButtonPressed() {
        print("soundButton")
    }
    
    @objc func loopButtonPressed() {
        print("loopButton")
    }
    
    @objc func addFlashcardButtonPressed() {
        print("adding flashcard")
    }

Complete Code

import UIKit

class ResultsController: UIViewController {

//MARK: - Info    
    let cellID = "SoundItOutCell"
    
//MARK: - Views
    
    var centerTitle: UILabel = {
       
        let label = UILabel(frame: CGRect(x: 10, y: 0, width: 50, height: 40))
        label.backgroundColor = K.Colors.purple
        label.font = UIFont.boldSystemFont(ofSize: 30)
        label.text = "Aura"
        label.numberOfLines = 2
        label.textColor = .white
        label.textAlignment = .center
        return label
        
    }()
    
    var languageBarView: UIView = {
        
        let view = UIView()
        view.backgroundColor = .white
        view.setUnderlineStyle(color: K.Colors.purple)
        return view
        
    }()
    
    var langStackView: UIStackView = {
        
        let stackView = UIStackView()
        stackView.backgroundColor = .white
        stackView.alignment = .center
        stackView.distribution = .fillEqually
        return stackView
        
    }()
    
    var languageButton: UIButton = {
        
        let button = UIButton()
        button.setTitle("Japanese", for: .normal)
        button.addTarget(self, action: #selector(languageButtonPressed), for: .touchUpInside)
        button.backgroundColor = .white
        button.setTitleColor(UIColor.systemBlue, for: .normal)
        return button
        
    }()
    
    var swapButton: UIButton = {
        
        let button = UIButton()
        button.setImage(UIImage(systemName: "repeat"), for: .normal)
        button.addTarget(self, action: #selector(swapButtonPressed), for: .touchUpInside)
        button.tintColor = .black
        button.backgroundColor = .white
        return button
        
    }()
    
    var englishLabel: UILabel = {
        
        let label = UILabel()
        label.text = "English"
        label.textColor = .black
        label.backgroundColor = .white
        label.textAlignment = .center
        return label
        
    }()
    
    var textViewBackgroundView = UIView()
    
    var textView: UITextView = {
        
        let textView = UITextView()
        textView.returnKeyType = .search
        textView.text = "Enter text"
        textView.textColor = .lightGray
        textView.font = .systemFont(ofSize: 20)
        textView.textContainerInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 50)
        return textView
    
    }()
    
    var cancelButton: UIButton = {
        
        let button = UIButton()
        button.setImage(UIImage(systemName: "multiply"), for: .normal)
        button.backgroundColor = .white
        button.tintColor = .black
        button.addTarget(self, action: #selector(cancelButtonPressed), for: .touchUpInside)
        button.isHidden = true
        return button
        
    }()
    
    var scrollView: UIScrollView = {
        
        let scrollView = UIScrollView()
        scrollView.backgroundColor = K.Colors.lightGrey
        return scrollView
        
    }()
    
    var contentView: UIView = {
        
        let view = UIView()
        view.backgroundColor = K.Colors.lightGrey
        return view
        
    }()
    
    var resultCardView: UIView = {
        
        let view = UIView()
        view.backgroundColor = .white
        view.roundCorners(cornerRadius: 10)
        return view
        
    }()
    
    var topLabel = UILabel()
    
    var bottomLabel = UILabel()
    
    var soundButton: UIButton = {
        
        let button = UIButton()
        button.setImage(UIImage(systemName: "speaker.3.fill"), for: .normal)
        button.backgroundColor = .white
        button.tintColor = .black
        button.addTarget(self, action: #selector(soundButtonPressed), for: .touchUpInside)
        return button
        
    }()
    
    var loopButton: UIButton = {
        
        let button = UIButton()
        button.setImage(UIImage(systemName: "repeat"), for: .normal)
        button.backgroundColor = .white
        button.tintColor = .black
        button.addTarget(self, action: #selector(loopButtonPressed), for: .touchUpInside)
        return button
        
    }()
    
    var lineDividerView: UIView = {
        let view = UIView()
        view.backgroundColor = K.Colors.purple
        return view
    }()
    
    var addFlashcardButton: UIButton = {
       
        let button = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
        button.setImage(UIImage(systemName: "plus"), for: .normal)
        button.backgroundColor = K.Colors.purple
        button.tintColor = .white
        button.roundCorners(cornerRadius: 15)
        button.addTarget(self, action: #selector(addFlashcardButtonPressed), for: .touchUpInside)
        return button
        
    }()
    
    // Background Views
    let resultBackgroundView = UIView ()
    
    let addFlashcardBackgroundView = UIView()

//MARK: - Class Functions
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupView()
        view.backgroundColor = K.Colors.lightGrey
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        
        setupShadows()

    }
}

extension ResultsController {
    
//MARK:- View Setup Functions
    
    func setupView() {
        self.setupToHideKeyboardOnTapOnView()
        setupNavBar()
        setupLanguageSelectionView()
        setupTextView()
        setupScrollView()
    }
    
    func setupShadows() {
        textViewBackgroundView.setShadow(color: UIColor.black, opacity: 0.3, offset: .init(width: 0, height: 3), radius: 2)
        resultBackgroundView.setShadow(color: .black, opacity: 0.3, offset: CGSize(width: 5, height: 5), radius: 2, cornerRadius: 10)
        addFlashcardBackgroundView.setShadow(color: .black, opacity: 0.5, offset: CGSize(width: 2, height: 2), radius: 2, cornerRadius: 15)
    }
    
    func setupNavBar() {
        
        // Add Center Title
        self.navigationItem.titleView = centerTitle
        
        // Add userbutton
        self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(systemName: "person"),
                                                                 style: .plain,
                                                                 target: self,
                                                                 action: #selector(profileButtonTapped))
        
        // Make bar color purple, and buttons white
        self.navigationController?.navigationBar.tintColor = .white
        self.navigationController?.navigationBar.barTintColor = K.Colors.purple

    }
    
    func setupLanguageSelectionView() {
        
        // Add Language Bar View
        view.addSubview(languageBarView)
        
        languageBarView.anchor(top: view.safeAreaLayoutGuide.topAnchor,
                               bottom: nil, leading: view.leadingAnchor,
                               trailing: view.trailingAnchor,
                               height: 60,
                               width: nil)
        
        
        // Add Stack View
        languageBarView.addSubview(langStackView)
        
        langStackView.anchor(top: languageBarView.topAnchor,
                             bottom: languageBarView.bottomAnchor,
                             leading: languageBarView.leadingAnchor,
                             trailing: languageBarView.trailingAnchor,
                             height: nil,
                             width: nil,
                             padding: UIEdgeInsets(top: 0, left: 0, bottom: -2, right: 0))
       
        // Add Language Button
        langStackView.addArrangedSubview(languageButton)
        
        // Add Swap Button
        langStackView.addArrangedSubview(swapButton)
        
        // Add English Label
        langStackView.addArrangedSubview(englishLabel)
    }
    
    func setupTextView() {
        
        // Add View
        view.addSubview(textViewBackgroundView)
        
        textViewBackgroundView.anchor(top: langStackView.bottomAnchor,
                                      bottom: nil,
                                      leading: view.leadingAnchor,
                                      trailing: view.trailingAnchor,
                                      height: 60,
                                      width: nil,
                                      padding: UIEdgeInsets(top: 2, left: 0, bottom: 0, right: 0))
        
        // Add TextView
        textView.delegate = self
        
        view.addSubview(textView)
        
        textView.anchor(top: textViewBackgroundView.topAnchor,
                        bottom: textViewBackgroundView.bottomAnchor,
                        leading: textViewBackgroundView.leadingAnchor,
                        trailing: textViewBackgroundView.trailingAnchor,
                        height: nil,
                        width: nil,
                        padding: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0))
        
        
        // Add X Button
        view.addSubview(cancelButton)
        
        cancelButton.anchor(top: textView.topAnchor,
                            bottom: nil,
                            leading: nil,
                            trailing: textView.trailingAnchor,
                            height: 40,
                            width: 40,
                            padding: UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0))
    }
    
    func setupScrollView() {
        
        // Add scroll view and content view
        view.addSubview(scrollView)
        view.sendSubviewToBack(scrollView)
        scrollView.addSubview(contentView)
        
        // Anchor Scroll View
        scrollView.anchorXCenter(top: textView.topAnchor,
                                 bottom: view.safeAreaLayoutGuide.bottomAnchor,
                                 centerAnchor: view.centerXAnchor,
                                 width: view.widthAnchor,
                                 height: nil)

        // Anchor Content View
        contentView.anchorXCenter(top: scrollView.topAnchor,
                                  bottom: scrollView.bottomAnchor,
                                  centerAnchor: scrollView.centerXAnchor,
                                  width: scrollView.widthAnchor,
                                  height: nil)
        
        
        // Setup Results Background
        contentView.addSubview(resultBackgroundView)
        
        resultBackgroundView.anchorXCenter(top: contentView.topAnchor,
                                           bottom: nil,
                                           centerAnchor: contentView.centerXAnchor,
                                           width: contentView.widthAnchor,
                                           height: nil,
                                           padding: UIEdgeInsets(top: 90, left: 0, bottom: 0, right: 0),
                                           widthOffset: -40)

        // Setup Results Card
        resultBackgroundView.addSubview(resultCardView)
        
        resultCardView.anchorXCenter(top: resultBackgroundView.topAnchor,
                                     bottom: resultBackgroundView.bottomAnchor,
                                     centerAnchor: resultBackgroundView.centerXAnchor,
                                     width: resultBackgroundView.widthAnchor,
                                     height: nil)
        
        setupResultsView(resultCardView)
    }
    
    func setupResultsView(_ resultCardView: UIView) {
   
        let searchInput = "Hello"
        let searchOutput = "Yo what's up dog congratulations"
        
        // Configure Top Label
        topLabel.attributedText = NSAttributedString(string: searchInput)
        topLabel.configureBasedOnInput()
        
        // Configure Bottom Label
        bottomLabel.attributedText = NSAttributedString(string: searchOutput)
        bottomLabel.configureBasedOnInput()
        
        // Add Flashcard Button to its Background View
        addFlashcardBackgroundView.addSubview(addFlashcardButton)
        
        addFlashcardButton.anchor(top: addFlashcardBackgroundView.topAnchor,
                                  bottom: addFlashcardBackgroundView.bottomAnchor,
                                  leading: addFlashcardBackgroundView.leadingAnchor,
                                  trailing: addFlashcardBackgroundView.trailingAnchor,
                                  height: nil,
                                  width: nil)
                
        // Add subviews to Result Card
        resultCardView.addSubview(topLabel)
        resultCardView.addSubview(bottomLabel)
        resultCardView.addSubview(soundButton)
        resultCardView.addSubview(loopButton)
        resultCardView.addSubview(lineDividerView)
        resultCardView.addSubview(addFlashcardBackgroundView)
        
        // Autolayout Constraints For Result Card Subviews
        topLabel.translatesAutoresizingMaskIntoConstraints = false
        topLabel.topAnchor.constraint(equalTo: resultCardView.topAnchor, constant: 10).isActive = true
        topLabel.centerXAnchor.constraint(equalTo: resultCardView.centerXAnchor, constant: 0).isActive = true
        topLabel.leadingAnchor.constraint(greaterThanOrEqualTo: resultCardView.leadingAnchor, constant: 10).isActive = true
        topLabel.trailingAnchor.constraint(lessThanOrEqualTo: resultCardView.trailingAnchor, constant: -10).isActive = true
        
        lineDividerView.anchor(top: topLabel.bottomAnchor,
                               bottom: nil, leading: resultCardView.leadingAnchor,
                               trailing: resultCardView.trailingAnchor,
                               height: 1,
                               width: nil,
                               padding: UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0))
        
        loopButton.anchor(top: lineDividerView.bottomAnchor,
                          bottom: nil,
                          leading: nil,
                          trailing: resultCardView.trailingAnchor,
                          height: nil,
                          width: nil,
                          padding: UIEdgeInsets(top: 10, left: 0, bottom: 0, right: -10))
        
        soundButton.anchor(top: lineDividerView.bottomAnchor,
                           bottom: nil,
                           leading: nil,
                           trailing: loopButton.leadingAnchor,
                           height: nil,
                           width: nil,
                           padding: UIEdgeInsets(top: 10, left: 0, bottom: 0, right: -10))
                
        bottomLabel.translatesAutoresizingMaskIntoConstraints = false
        bottomLabel.topAnchor.constraint(equalTo: soundButton.bottomAnchor, constant: 10).isActive = true
        bottomLabel.centerXAnchor.constraint(equalTo: resultCardView.centerXAnchor, constant: 0).isActive = true
        bottomLabel.leadingAnchor.constraint(greaterThanOrEqualTo: resultCardView.leadingAnchor, constant: 10).isActive = true
        bottomLabel.trailingAnchor.constraint(lessThanOrEqualTo: resultCardView.trailingAnchor, constant: -10).isActive = true
        
        
        addFlashcardBackgroundView.anchor(top: bottomLabel.bottomAnchor,
                                          bottom: resultCardView.bottomAnchor,
                                          leading: nil,
                                          trailing: resultCardView.trailingAnchor,
                                          height: 30,
                                          width: 30,
                                          padding: UIEdgeInsets(top: 10, left: 0, bottom: -10, right: -10))
    }
    
//MARK:- Selector Functions
    
    @objc func profileButtonTapped() {
        print(0)
    }
    
    @objc func languageButtonPressed() {
        print(1)
    }
    
    @objc func swapButtonPressed() {
        print(2)
    }
    
    @objc func cancelButtonPressed() {
        textView.text = ""
        textView.textColor = .lightGray
        textView.text = "Enter text"
        cancelButton.isHidden = true
    }
    
    @objc func soundButtonPressed() {
        print("soundButton")
    }
    
    @objc func loopButtonPressed() {
        print("loopButton")
    }
    
    @objc func addFlashcardButtonPressed() {
        print("adding flashcard")
    }
        
}

Output: Circled Buttons are ones that don't work

enter image description here

0 Answers
Related