According to the Apple docs, hidden UIButtons
should not receive tap events.
However, our app has a UIButton
receiving tap events despite being hidden.
This function is the IB Action
invoked when the button is tapped. When the button is removed from Storyboard, this function doesn't get invoked. When the button is added to Storyboard, the function gets invoked -- even though the button is hidden.
To verify that the button is hidden, we put a breakpoint inside the function and ran expr sender.hidden
from the Xcode debugger. The result: true.
The stack trace shows the IB Action is triggered by code in UIApplicationMain, not our code.
Through the Connections Inspector, we confirmed there is no other trigger for the IB Action except the mysterious button.
Thoroughly confused. Suggestions?
@IBAction func buttonTapped(sender: UIButton) {
// If here, handle tap
...
}
The problem was an incomplete UIButton extension that didn't account for visibility in determining hit tests.
This function correctly handles the case where UIButtons are hidden.
extension UIButton {
public override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
// Ignore if button hidden
if self.hidden {
return nil
}
// If here, button visible so expand hit area
let hitSize = CGFloat(56.0)
let buttonSize = self.frame.size
let widthToAdd = (hitSize - buttonSize.width > 0) ? hitSize - buttonSize.width : 0
let heightToAdd = (hitSize - buttonSize.height > 0) ? hitSize - buttonSize.height : 0
let largerFrame = CGRect(x: 0-(widthToAdd/2), y: 0-(heightToAdd/2), width: buttonSize.width+widthToAdd, height: buttonSize.height+heightToAdd)
return (CGRectContainsPoint(largerFrame, point)) ? self : nil
}
}