Skip to content
This repository has been archived by the owner on Nov 29, 2022. It is now read-only.

Gestures not reaching custom view in iOS7 when tableview has a background view #47

Closed
atetlaw opened this issue Dec 15, 2014 · 5 comments · May be fixed by #126
Closed

Gestures not reaching custom view in iOS7 when tableview has a background view #47

atetlaw opened this issue Dec 15, 2014 · 5 comments · May be fixed by #126

Comments

@atetlaw
Copy link

atetlaw commented Dec 15, 2014

Hi, here's curly one.

It appears that if you insert the empty view beneath the UITableViewWrapperView in the tableview's hierarchy, gestures don't work in iOS7.

Normally it's fine, since inserting the empty view at index 1 puts it above this view (UITableViewWrapperView view is usually at index 0)

But if you've set a background view for your tableview, the background view is at index 0 and the UITableViewWrapperView is at index 1. Thus the empty view is inserted beneath the UITableViewWrapperView view.

This is only a problem in iOS7. In iOS8 inserting the empty view beneath the UITableViewWrapperView view doesn't seem to matter, gestures still work.

Here's my solution:

if ([self isKindOfClass:[UITableView class]] && self.subviews.count > 1) {
    UITableView *tableview = (UITableView *)self;
    if (tableview.backgroundView && self.subviews.count > 2) {
       [tableview insertSubview:view atIndex:2];
   } else {
       [tableview insertSubview:view atIndex:1];
   }
}

I can submit a pull request if you think the above is not crazy.

@dzenbot
Copy link
Owner

dzenbot commented Dec 15, 2014

That makes sense.
If you could make it compatible with UICollectionView too, that would be great.

So instead of [self isKindOfClass:[UITableView class]] check for [self respondsToSelector:@selector(backgroundView)]

@bartvandendriessche
Copy link
Contributor

Just ran into the same issue.

Unfortunately, if the UITableView has a backgroundView and a UIRefreshControl, then index 2 is not correct and the DZNEmptyDataSetView needs to be inserted at index 3 instead.

Not sure how to best approach this without it being brittle towards the future :/

@dzenbot
Copy link
Owner

dzenbot commented Dec 15, 2014

In that case, we must make sure it gets inserted at the latest index, right?

NSIndex lastIndex = self.subviews.count+1;
[self insertSubview:view atIndex:lastIndex];

@bartvandendriessche
Copy link
Contributor

I would do that, but your original code specifically mentions inserting the DZNEmptyDataSetView at index 1 in case the UITableView has a header or footer.

Inserting at the last index is the same as just doing [self addSubview:view].

A hacky workaround that doesn't look for a specific classname would be something like this:

        if (!view.superview) {
            // Send the view to back, in case a header and/or footer is present
            if ([self isKindOfClass:[UITableView class]] && self.subviews.count > 1) {
                __block NSUInteger *highestIndexOfTableViewFillingSubview = 0;
                [self.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) {
                    if (CGRectEqualToRect(subview.bounds, self.frame)) {
                        highestIndexOfTableViewFillingSubview = idx;
                    }
                }];
                [self insertSubview:view atIndex:highestIndexOfTableViewFillingSubview+1];
            }
            else {
                [self addSubview:view];
            }
        }

But I don't really love that approach either.

Edit:
I don't know if this is an issue on iOS 6 as well, but maybe we could wrap this hierarchy code in a iOS version check ?

@bartvandendriessche
Copy link
Contributor

Something like this:

if (!view.superview) {
  // Send the view to back, in case a header and/or footer is present
  if ([self isKindOfClass:[UITableView class]] && self.subviews.count > 1) {
    if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1 &&
        floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) {
      // annoying hack to work around an iOS 7 issue
      __block NSUInteger *highestIndexOfTableViewFillingSubview = 0;
      [self.subviews enumerateObjectsUsingBlock:^(UIView *subview, NSUInteger idx, BOOL *stop) {
      if (CGRectEqualToRect(subview.bounds, self.frame)) {
            highestIndexOfTableViewFillingSubview = idx;
      }
    }];
      [self insertSubview:view atIndex:highestIndexOfTableViewFillingSubview+1];
    }
    else {
      [self insertSubview:view atIndex:1];
    }
  }
  else {
    [self addSubview:view];
  }
}

bartvandendriessche added a commit to bartvandendriessche/DZNEmptyDataSet that referenced this issue Aug 25, 2015
This fixes dzenbot#47

In a nutshell, this pull request toggles `UITableViewWrapperView`'s
`userInteractionEnabled` property off or on when the `emptyDataSetView`
appears or disappears.

The main concern here I suppose is the check for
"UITableViewWrapperView" since that is a private API. This call is
guarded by a version check, so shouldn't break in future releases, but
I'm not sure if checking for this class could cause an app to be
rejected.

For what it's worth, validating an Archive containing this code didn't
cause any private API flags to be raised.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
3 participants