The other day, Soroush wrote a great post about hitTest(_:with:) (you should check it out), which reminded me of a problem I solved the other week: I wanted to increase a UIButton ’s tap area, without increasing the button’s frame.

The following code would go in one of the button’s superviews ; for example, you might have a mainContainer , which has a UIStackView that contains the button — we’d implement it in mainContainer :

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let biggerButtonFrame = theButton.frame.insetBy(dx: -30, dy: -30) // 1 if biggerButtonFrame.contains(point) { // 2 return theButton // 3 } return super.hitTest(point, with: event) // 4 }

We first create a rect that is 30px larger than our button, both horizontally and vertically (1) and we check if it contains the point (2): if it does, we return the button (3), otherwise we fallback to super (4). At (1) we might need to convert between coordinate systems and at (2) we might also want to check if the button is enabled and visible, if it can have different states.

If you google increase uibutton tap area , you’ll get quite a few results, mentioning either increasing imageEdgeInsets / titleEdgeInsets (not quite what we want), or using pointInside(point:with:) . The approach of the latter is basically the same as we saw above, just that the implementation is done on the button itself, not in one of its superviews :

override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { let biggerFrame = bounds.insetBy(dx: -30, dy: -30) return biggerFrame.contains(point) }

Sometimes, a button might be part of a view controller’s view , or used as a customView for a UIBarButtonItem , in which case we don’t have access to the implementation of the superview , so we need to use this approach.

At some point, I didn’t really want to write this post anymore, seeing so much information about this dating back to 2010, but, in the end, I think that any knowledge shared is better than kept.