Search code examples
iosswiftuikit

Swift button from nested UIView is not clickable


I have a ViewController and another UIView called MySubview which contains a simple button.

If I add MySubview into ViewController the button is unclickable. However if I put the button directly inside ViewController everything works as expected.

Example:

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = MySubview()
        view.addSubview(button)
        
        button.translatesAutoresizingMaskIntoConstraints = false
        button.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
        button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
    }
}

class MySubview: UIView {
    
    let button: UIButton = {
        let button = UIButton()
        button.setTitle("MyButton", for: .normal)
        button.setTitleColor(.label, for: .normal)
        button.addTarget(self, action: #selector(myfunc), for: .touchUpInside)
        return button
    }()
    
    @objc func myfunc() {
        print("clicked")
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        backgroundColor = .red
        addSubview(button)
        
        button.translatesAutoresizingMaskIntoConstraints = false
        
        button.topAnchor.constraint(equalTo: topAnchor, constant: 0).isActive = true
        button.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0).isActive = true
        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

When I click on the button I do not see printed message.


Solution

  • Your code is confused, if I understand well take a look to my code below, declare your button and your view under your controller class:

    class ViewController: UIViewController {
    
    let button: UIButton = {
        let button = UIButton()
        button.setTitle("MyButton", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.backgroundColor = .black
        button.addTarget(self, action: #selector(myfunc), for: .touchUpInside)
        return button
    }()
    
    let mysubview = UIView()
    ...
    

    now in viewDidLoad set constraints like this:

    override func viewDidLoad() {
        super.viewDidLoad()
        
        mysubview.backgroundColor = .red
        
        view.addSubview(mysubview)
        mysubview.translatesAutoresizingMaskIntoConstraints = false
        mysubview.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
        mysubview.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
        mysubview.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
        mysubview.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
        
        mysubview.addSubview(button)
        
        button.translatesAutoresizingMaskIntoConstraints = false
        button.topAnchor.constraint(equalTo: mysubview.topAnchor, constant: 20).isActive = true
        button.leadingAnchor.constraint(equalTo: mysubview.leadingAnchor, constant: 20).isActive = true
        button.trailingAnchor.constraint(equalTo: mysubview.trailingAnchor, constant: -20).isActive = true
        button.heightAnchor.constraint(equalToConstant: 50).isActive = true
    }
    

    now add your func

    @objc func myfunc() {
        print("clicked")
    }
    

    complete code:

    import UIKit
    
    class ViewController: UIViewController {
    
    let button: UIButton = {
        let button = UIButton()
        button.setTitle("MyButton", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.backgroundColor = .black
        button.addTarget(self, action: #selector(myfunc), for: .touchUpInside)
        return button
    }()
    
    let mysubview = UIView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        mysubview.backgroundColor = .red
        
        view.addSubview(mysubview)
        mysubview.translatesAutoresizingMaskIntoConstraints = false
        mysubview.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
        mysubview.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
        mysubview.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
        mysubview.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
        
        mysubview.addSubview(button)
        
        button.translatesAutoresizingMaskIntoConstraints = false
        button.topAnchor.constraint(equalTo: mysubview.topAnchor, constant: 20).isActive = true
        button.leadingAnchor.constraint(equalTo: mysubview.leadingAnchor, constant: 20).isActive = true
        button.trailingAnchor.constraint(equalTo: mysubview.trailingAnchor, constant: -20).isActive = true
        button.heightAnchor.constraint(equalToConstant: 50).isActive = true
    }
    
     @objc func myfunc() {
        print("clicked")
     }
    }