background

This article is to fix the UIControl and UITapGestureRecognizer conflict bug, after the in-depth understanding of UIButton

At the scene of the Bug

In my project I have a card with a view structure like this

As shown in the figure:

  • A gesture has been added to the blue view
  • The axe picturesSuperView isBlue viewIt has one on itUIButton
  • The followingThe yellow viewandThe axe picturesFlat level, superView alsoBlue viewI put one on topUIControl

Complex story

When I happily finished writing the UI, I tested myself three times, five times and two times. Well, it was perfect.

On Friday night, when I was getting ready to leave work, a test student reported a bug to me suddenly. The UIControl jump logic in the lower right corner was replaced by the following gesture jump logic

I thought to myself, how could this be wrong? I had tested myself all good, and the jump in the upper right corner is all right

Then I opened Xcode and debugged it, and there was a problem

UIButton on the top right is good, UIButton inherits from UIControl, so they have the same event handling logic, but there’s a problem with UIControl’s own UI jumping,

Due to the urgency of time, I also did not delve into the research, can only fix first

Fixing code

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    return! [touch.view isKindOfClass:UIControl.class];
}
Copy the code

The logic of this code is so simple that I won’t talk any more

Debug

After going online, I was struggling with this point all the time, so I dug into it and then explored why this Bug was caused

I started out thinking about the response chain, doing this mess of code testing

The discovery was not caused by a chain of responses

Searched on the net along while, also did not search out what result, then thought along while, also did not have too good train of thought, have to ask for help group friend

Suddenly before the colleague lost such a screenshot

I then asked him for a link to the document, but ** the official document seems to have been updated, I couldn’t find the original content of the screenshot above, he gave me a link to the blog **

So with that in mind, what I’m going to do is I’m going to put a breakpoint on all of the UIButton methods, and I’m going to step through it, and I’ll always see a clue

toUIButtonAll methods set breakpoint commands

br set -r '\[UIButton .*\]$'

I don’t need to go over the LLDB debugging commands, but I will post a link to learn LLDB debugging

The following results are obtained

UIButton partial method

Because there are too many UIButton methods (311 in total), I cannot capture all the screenshots. I only capture the key method that causes this bug, see the image highlighting method

toUIControlAll methods set breakpoint commands

br set -r '\[UIControl .*\]$'

UIControl all methods

The two pictures can see clearly that without this method in the UIControl [UIButton gestureRecognizerShouldBegin:]

So that’s probably it, and then I put a break point on this method

br set -F "-[UIButton gestureRecognizerShouldBegin:]"

And you get something like this

Can clearly see [UIGestureRecognizer _shouldBegin] calls the inside [UIButton gestureRecognizerShouldBegin:]

And then look at

At this point, the cause of the entire bug is clear

The main reason is the method of UIButton [UIButton gestureRecognizerShouldBegin:]

Through this bug, I also updated my knowledge of UIButton and UIControl

Many thanks to the help of group friends and former colleagues who have provided a good direction

Test the Demo

Refer to the link

  • IOS Touch event family bucket
  • Attaching Gesture Recognizers to UIKit Controls
  • Dance with debugger – waltz of LLDB
  • Do you know how to debug Swift using LLDB?