1

I'm trying to add a button to my stack view. The button has a buttonTapped method that should be called when it is tapped. The problem is it is never being called, the button does not seem to be clickable.

class CustomButton: UIViewController {
    var buttonDelegate: ButtonDelegate?

    let button = UIButton(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width - 40, height: 30))
    
    init(label: String) {
        button.setTitle(label, for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.backgroundColor = .systemBlue
        super.init(nibName: nil, bundle: nil)
    }
    
    @objc func buttonTapped() {
        print("this never gets printed")
        buttonDelegate?.buttonTapped(buttonType: .submit)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
        view.addSubview(button)
    }
}

And then my main view controller:

protocol ButtonDelegate {
    func buttonTapped(buttonType: ButtonType)
}

class DynamicViewController: UIViewController, ButtonDelegate {
    lazy var scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        return scrollView
    }()

    lazy var stackView: UIStackView = {
        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.distribution = .equalSpacing
        stackView.translatesAutoresizingMaskIntoConstraints = false
        
        return stackView
    }()


    lazy var contentView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints = false
        return view
    }()

    private func setupViews() {
        view.addSubview(scrollView)
        scrollView.addSubview(contentView)
        contentView.addSubview(stackView)
        
        let btn = CustomButton(label: "hi")
        btn.buttonDelegate = self
        self.stackView.addArrangedSubview(btn.view)
    }

    func buttonTapped(buttonType: ButtonType) {
        print("also never gets printed")
    }
}

There is nothing overlapping the button or anything like that: enter image description here

My question is why the button is not clickable.

ffritz
  • 2,180
  • 1
  • 28
  • 64

1 Answers1

2

You are adding the view controller as a subview. So you also need to add as a child. Add bellow code after self.stackView.addArrangedSubview(btn.view) this line.

self.addChild(btn)
btn.didMove(toParent: self)
Raja Kishan
  • 16,767
  • 2
  • 26
  • 52
  • 2
    The reason this is needed: You create an instance of your CustomButton (view controller) class in a local variable in your `setupViews()` method. Once that function returns, the variable `btn` that holds a strong reference to your newly created `CustomButton` view controller goes out of scope. You put the CustomButton view controller's view into a stack view, but never kept a strong reference to the view controller. As soon as the function returns, the view controller gets released and deallocated. – Duncan C Jan 28 '21 at 13:57