简体   繁体   中英

iOS: Why does hidden button still receive tap events?

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
    ...
}

Try to set enable = false like this:

button.enabled = false

For Swift 3 would be:

button.isEnabled = false

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
    }
}

A situation I encountered was that I was toggling between two different buttons based on application state. When I created the second of these two buttons, I copied and pasted the first. This also copied the first button's outlets.

I thought that the first button was being pressed when only the second button was showing, but in reality the second button was sending events to both the outlet I intended AND the one that was set when I copied the first button.

To determine if this is the case in your situation, go to the interface builder, select your button, and check that the touch events are set up exactly how you want in the connections inspector. If any of the connections are wrong, you can remove them by clicking the little 'x'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM