Button Action not called button.addTarget

I am learning swift 3, and following this guide, which was written before swift 3 and xcode 8.1, as such, I had to change a few things along the way. https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson5.html#//apple_ref/doc/uid/TP40015214-CH19-SW1


Here is the code to the point where I am stuck in creating the RatingControl. The problem is ratingButtonTapped does not get called. Doubly verified using a breakpoint. I do see that the initialization function is called, and so I know that button.addTarget is executed. Any ideas on what I am doing wrong?


import UIKit

class RatingControl: UIView {

required init?(coder aDecoder: NSCoder) {

super.init(coder: aDecoder)


let button = UIButton(frame: CGRect(x: 0, y: 0, width: 44, height: 44))

button.backgroundColor = UIColor.red

button.isEnabled = true

button.addTarget(self, action: #selector(RatingControl.ratingButtonTapped(button:)), for: .touchDown)

addSubview(button)

}

func ratingButtonTapped(button: UIButton) {

print("Button pressed ")

}

}

The selector specification looks correct for the method name in your code, so make sure 'User Interaction Enabled' is ticked in Attributes Inspector for the RatingControl when it's selected in IB. Do the same for the view object that contains it, and so on up to the top of that view hierarchy.

Hi goldsdad,


Thanks for your help. I have verified that the 'User Interaction Enabled' is checked for RatingControl, and the StackView. Other subViews within the stackview are working correctly, specifically, there is an action for another button "Set Default Label Text", but in this case, the action was configured using interface builder, as opposed to the programatic approach, and that action routine does get called.


eric

I think you should create the button in viewDidLoad and not in the init().

Hi Claude31,


I might be misunderstanding what you are asking me to do, but when I attempt to add the following lines of code to the RatingControl, I immediately get errors as it appears that viewDidLoad() is not a member function of the UIView class, and therefore cannot be overridden.


override func viewDidLoad() {

super.viewDidLoad()

}

You're right, it's a method of the viewController.


That's where you should put it, as well as the IBAction.

Try adding this property to the RatingControl class that you posted at the start of this thread.


    override var intrinsicContentSize: CGSize {
        return CGSize(width: 240, height: 44)
    }



These dimensions match the placeholder size of the RatingControl. Later in the tutorial, you will be instructed to add that property, but with the dimensions being calculated from the quantity and size of multiple buttons in the RatingControl.

I found a solution, in another discussion, where adding contraints to the RatingControl for height=44 and width=240 made the view start receiving the events. Now I can hit breakpoint for the ratingButtonTapped. I do not understand why not having the constraints prevented it from getting called.

SUrprising effectively.


may be the hitTest is confused to believe the button size is small (eg 0, 0) and does not intercept the event ?

The tutorial does tell you that the rating control should be given an override for intrinsicContentSize to make it work correctly inside a stack view. I guess you missed my post on 22nd November where I gave you the code for the override. The constraints you added do provide a workaround, though.


Note that intrinsicContentSize is a property of UIView in Swift 3, whereas UIView had method intrinsicContentSize() at the time the tutorial was written.

Button Action not called button.addTarget
 
 
Q