Subview button is not working

10.7k views Asked by At
masterBtn.addTarget(self, action: #selector(self.masterBed), for: UIControlEvents.touchUpInside)

i have used above code in subview but it doesn't fire function masterBed. the button within subview is not clickable

Full code:

let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
button.setTitleColor(.gray, for: .normal)
button.center = CGPoint(x: 380, y: 110)
button.setTitle(">", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
self.addSubview(button)

func buttonAction () {
    print("button pressed")
}
5

There are 5 answers

0
Vollan On BEST ANSWER

I believe the height and width of the subview remains 0 because the button is not bound to any edges and the button seem to define the height of its superview. You could always check this by settings clipToBounds = true. Its always good to call the lazy if you are using self within an view.

This should solve your problem:

class buttonView: UIView {
private lazy var button: UIButton = {
    let button = UIButton()
    button.setTitleColor(.gray, for: .normal)
    button.setTitle("MyButton", for: .normal)
    button.translatesAutoresizingMaskIntoConstraints = false
    button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
    return button
}()

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

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

func setup() {
    addSubview(button)
    
    addConstraint(NSLayoutConstraint(item: button, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 10))
    addConstraint(NSLayoutConstraint(item: button, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 10))
    addConstraint(NSLayoutConstraint(item: button, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0))
    addConstraint(NSLayoutConstraint(item: button, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: 0))
    addConstraint(NSLayoutConstraint(item: button, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 80))
    addConstraint(NSLayoutConstraint(item: button, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 35))
}

@objc func buttonAction() {
    //Do stuff
    }
}

Slightly unsure about the NSLayoutConstraints, since i use SnapKit or anchorpoints. But i think this should be correct.

0
Pradeep Tokalwad On

might be your subview is out off parent view frame so can you try to give same frame as parent view frame and try like this:

let button = UIButton(frame: self.frame)//Parent view frame
button.setTitleColor(.gray, for: .normal)
//button.center = CGPoint(x: 380, y: 110) // comment this line 
button.setTitle(">", for: .normal)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
self.addSubview(button)
13
Rahul Kumar On

I have edited your code as below, it's working.

Your ViewController Class

class ViewController: UIViewController, HomeViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        middleView()
    }

    func middleView() {
        let customView = HomeView(frame: CGRect(x: 60, y: 100, width: 250, height: 100))
        self.view.addSubview(customView)
        customView.backgroundColor = UIColor.green
        customView.delegate = self
    }

    func buttonAclicked(_ sender: UIButton) {
        print("button click action in viewController")
    }

}

HomeView Class

import UIKit

protocol HomeViewDelegate {

    func buttonAclicked(_ sender: UIButton)
}

class HomeView: UIView {

    var delegate:HomeViewDelegate?

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

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

    func initView() {
        let button = UIButton(frame: CGRect(x: 10, y: 10, width: 80, height: 35))
        self.addSubview(button)
        button.setTitleColor(.gray, for: .normal)
        button.setTitle("MyButton", for: .normal)
        button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
    }

    func buttonAction(_ sender: UIButton) {
        print("button pressed")
        delegate?.buttonAclicked(sender)
    }

}
0
Yan Cervantes On

inside on the Masterbed property, put userinteractionenbaled = true, that will fix the problem, other stuff is the addSubview... put that on the subView Item or Class.. like masterBed.addSubView(youurButton) and if you use userinteration on the button.. really has no sense because the button is already an object created for interacions.. it's the same thing if we put a button on UIImageView, we need activated on the property on the UIImageView, to interact with the button. like this Sample..

  class ViewController: UIViewController {

 let myImage: UIImageView = {
    let image = UIImageView()
    image.backgroundColor = UIColor.brown
    image.translatesAutoresizingMaskIntoConstraints = false
    image.isUserInteractionEnabled = true    // here activate the interaction needed
    image.image = UIImage(imageLiteralResourceName: "backgroundSE.jpg")
    return image
}()

let textLabel: UILabel = {
   let label = UILabel()
    label.text = "My App"
    label.textColor = UIColor.white
    label.font = UIFont.boldSystemFont(ofSize: 25)
    label.textAlignment = .center
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

lazy var sendMailButton: UIButton = {
    let button = UIButton(type: .system)
    button.setTitle("Send Mail", for: .normal)
    button.setTitleColor(.white, for: .normal)
    button.backgroundColor = UIColor(white: 0.5, alpha: 0.5)
    button.translatesAutoresizingMaskIntoConstraints = false
    button.layer.cornerRadius = 14
    button.addTarget(self, action: #selector(handleSendMail), for: .touchUpInside)
    return button
}()

override func viewDidLoad() {
    super.viewDidLoad()


    view.addSubview(myImage)
    myImage.addSubview(sendMailButton)
    myImage.addSubview(textLabel)

    setupLayouts()

}

@objc func handleSendMail() {
    print("Mail Sended")
}

I hope this help you and fix the problem, cheers!

0
Dmih On

I have same problem. To solve it just set isUserInteractionEnabled = true to PARENT view (view were you add button subview)