UIbutton doesn't respond to touch events

Viewed 802

My view hierarchy is something like this:

UIView -> UIStackView
             -> UIView
                -> PlayerView
             -> UIView
                -> UIStackView
                   UITextField (title)
                   UIButton (close)
                   UIButton (settings) etc...

My problem is following...When screen loads, if I click on the close or settings buttons it WORKS.

The problem is if I click first to the Player View to play video, then I stop a video and when I tap on any of the UIButtons it doesn't work. Button is active, but touch event doesn't fire. You can see player implementation here: github playerview example

The weird thing is...if I click on the UITextField (Title) then I'm able to click on the UIButtons again, and touch events are firing.

I have played with adding isUserInteractionEnabled = true to the UIView where I have the buttons but it didn't work.

here is a screenshot of UI debug tree

Player view object inspector

Player view hierarchy

2 Answers

Whether a control reacts to an event (e.g. a touch), depends on whether it is the first responder.
If the event is a touch, the UI element in which the touch occurred, becomes the 1st responder. This applies e.g. to an UIButton.
Since your buttons work as long as you did not play a video, this means that they are user interaction enabled, and the target action is assigned.
When you played and stopped a video, and only the UITextField but no button can become 1st responder, this means to me that only the UITextField is a view that can be tapped, but not the UIButtons. So the UIButtons must be covered by some other view that does not respond to the tap.
To check this, I suggest that you stop your app at a breakpoint, and tap in the Xcode debug area the Debug View Hierarchy button:

enter image description here

Then, you should see if your buttons are covered by something else.

EDIT:

One more idea: Maybe for some reason the property canBecomeFirstResponder of your button is not true (see here). Please check this in the debugger. If it is false, you might have success by setting it explicitly to true. To do so, you had to subclass your button, and override this var as

override var canBecomeFirstResponder: Bool {
  return true
}  

see here.

Found the problem. The selectedRateView had a height constraint of 0 with a priority of 1000. This caused the view to have a height of 0 even though the code was trying to set it's frame. For some reason, the child controls were still visible; but not receiving events.

For some reason, this wasn't being enforced on older versions of iOS. The selectedRateView was the height specified when setting the frame in code and it's children were receiving touch events.

Related