Stop UITableView consuming touch events so sliding

2019-03-27 18:09发布

问题:

I am about driven to despair trying to achieve something so simple.

I have a view with a menu that, using touchEvents slides from the left when it is gestured to do so with a horizontal swipe. I don't use gesture recognisers, I simply use the touchesBegan, touchesMoved, etc.. and track the x coordinate difference between the starting touch position, those in-between and the finishing touch position. It works great.

But, when in the body I have a UITableView, the touch events no longer find their way up the hierarchy to the view managing the menu. I tried to get around this by passing touches to superview/nextResponder, which sort of works, but I see a touchesBegan and 2 touchesMoved calls before it simply stops being processed further up the hierarchy.

Specifically, I have a SlideMenuView, in which there is a menu view and a body view. Inside the body view, I have at some point the UITableView. I see (via NSLog) that the touches* methods are called from start to finish just fine. I pass them on to nextResponder and begin to see them in SlideMenuView also - but after 2 calls to touchesMoved, they seem to stop in SlideMenuView but continue in my UITableView.

I am overriding the UITableView to do this, but I have changed nothing more inside of it.

I know that this must be possible, as it is in the Facebook app. You can swipe anywhere in the body, which is scrollable, horizontally and reveal the menu. I want the same thing to naturally occur here, but it appears as though something weird is happening, and the UITableView is consuming or destroying the events.

Can anybody help me out with this? Somebody must have achieved this in a clean way.

回答1:

Okay, for anybody interested - I found a clean solution.

Apple know what they're doing. Back in the day we used to override touchesBegan, ... but then they introduced GestureRecognizers. For some controls, such as the UIScrollView (and any subclasses, such as UITableView), they seem to butcher their event responder system. I was at fault for assuming that the Gesture Recognizers don't do anything special, and simply hook in to these touchesBegan, ... methods - this is not correct.

The safest way is to use the Gesture Recognizers. Specifically, there are some options on them that can make all the difference. Such as .cancelsTouchesInView = YES in my case.

So what I did, is use a PanGestureRecognizer on the Menu View, set .cancelsTouchesInView to YES, and it works. I am going to avoid touchesBegan, ... like the plague, and write custom gesture recognisers for anything complex.

I hope this helps somebody pulling their hair out like I was !