UIButton not working correctly in iOS 7

I found the solution last night. Okay, so what happens is that I put the above table view and UIView elements onto a target frame.

I'm not 100% sure, but it seems that in iOS6 the buttons respond to events irrespective of where they are placed. For some reason in iOS7 when the button sits outside of the frame it is supposed to be in, it ignores touch events, even though it does get displayed.

I solved the problem by positioning the view's frame in the correct place so it overlays the button.

If I can find any documentation around this, I will post here.

Thanks!


I have just faced to this problem. According to @Guntis Treulands advice, I decided to check what happens if I override hitTest:withEvent: method in my custom header view. This method ignores view objects that are hidden, that have disabled user interactions, or have an alpha level less than 0.01. This method does not take the view’s content into account when determining a hit. Thus, a view can still be returned even if the specified point is in a transparent portion of that view’s content and now, after it has been overridden, receives touches outside the bounds. It did the trick for me. Hope it helps you, guys.

swift

override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
    guard !isHidden, alpha > 0 else {
      return super.hitTest(point, with: event)
    }
    
    for subview in subviews {
      let subpoint = subview.convert(point, from: self)
      let result = subview.hitTest(subpoint, with: event)
      if result != nil {
        return result
      }
    }
    return super.hitTest(point, with: event)
}

Objective-C

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (!self.clipsToBounds && !self.hidden && self.alpha > 0) {
        for (UIView *subview in self.subviews.reverseObjectEnumerator) {
            CGPoint subPoint = [subview convertPoint:point fromView:self];
            UIView *result = [subview hitTest:subPoint withEvent:event];
            if (result != nil) {
                return result;
            }
        }
    }
    // use this to pass the 'touch' onward in case no subviews trigger the touch
    return [super hitTest:point withEvent:event];
}

Just as an alternative answer - Actually for me, this has never worked (if uibutton is outside it's parent view, then it will not receive touch.) - But in some cases, it is required to have the button outside it's boundaries.

For that reason, there is a hittest function, which can be overridden - to simply check parent view all subviews to find uibutton that is placed outside parent views boundaries. (You would then check each subview, if it is uibutton type, and if touched coordinates are inside uibuttons frame.

By default hittest function skips checking views, that are outside boundaries.

Hittest example: https://stackoverflow.com/questions/17246488/best-way-to-perform-the-hit-test-objective-c .