Processing mechanism
For iOS event handling, the first thing you should do is find a view that handles the Click event and then handle the click event in the view that you found.
The processing principle is as follows:
? When the user taps the screen, a touch event is generated and the event is added to an event queue managed by UIApplication
? UIApplication will take the first event out of the event queue for distribution for processing, typically sending an event to the application's main window (UIWindow)
? The main window calls the Hittest:withevent: Method finds the most appropriate UIView in the view (UIView) hierarchy to handle touch events
(hittest:withevent: Actually is a method of UIView, UIWindow inherit from UIView, so the main window UIWindow also belongs to the view of one)
? Hittest:withevent: Method The approximate processing process is this:
First call the current view's Pointinside:withevent: method to determine whether the touch point is within the current view:
? If Pointinside:withevent: Method returns no, indicating that the touch point is not in the current view, the current view of the Hittest:withevent: return nil
? If the Pointinside:withevent: method returns Yes, indicating that the touch point is within the current view, traverse all the child views of the current view (subviews) and call the hittest:withevent of the Child View: Method repeats the previous steps, The traversal order of a child view is from top to bottom, that is, traversing forward from the end of the subviews array, until there is a hittest:withevent of the child View: The method returns a non-empty object, or all the child views are traversed:
? If the hittest:withevent of the child view is returned for the first time: The method returns a non-empty object, the current view's Hittest:withevent: method returns this object, processing ends
? If all child views are hittest:withevent: The method returns nil, the current view's Hittest:withevent: method returns the current view itself (self)
? Finally, this touch event is handed to the main window's hittest:withevent: Method returned by the view object to be processed. My number iOS development: Iosdevtip
Case analysis
Load a lgfirstview on the self.view of Uiviewcontroller
Lgfirstview There's a uibutton we call it Buttonfirst
Then, a lgsecondview is loaded on the Self.view, just above the Lgfirstview.
Lgsecondview also has a uibutton we call it Buttonsecond
Under normal circumstances:
The user clicks on the Lgsecondview (the clicked Point is not on the Buttonsecond, but the Buttonfirst is sad), the event processing flow is as follows:
1) Call UIWindow's Hittest:withevent: Method, Hittest:withevent: Method calls Pointinside:withevent: Method. At this point pointinside:withevent: Returns Yes, indicating that the touch event is above UIWindow.
2) go through the sub-view above UIWindow, that is, Self.view. The same is also called the Self.view Hittest:withevent: Method, Hittest:withevent: Method calls the Pointinside:withevent: method. At this point pointinside:withevent: Returns Yes, indicating that the touch event is above Self.view.
3) go through the sub-views on the Self.view, i.e. Lgfirstview and Lgsecondview. (Note: The traversal order of the child view is from top to bottom, which is traversing forward from the end of the subviews array).
4) So first call Lgsecondview's Hittest:withevent: Method, Hittest:withevent: Method calls Pointinside:withevent: Method. At this point pointinside:withevent: Returns Yes, indicating that the touch event is above Lgsecondview. (You won't be able to traverse Lgfirstview at this point, so as you wish, the Buttonfirst click event will not be called)
5) It's not over yet, and then go back to all the child views on the Lgsecondview, and the Hittest:withevent: method returns nil for all the child views, because Lgsecondview has only secondbutton on it, And the clicked Point is not Secondbutton.
6) Final Hittest:withevent: The method returns the current view itself (self), and Lgsecondview no event to process. The whole process is over.
What if we want Buttonfirst to also respond to click events? Method One:
We add the following code to Lgsecondview:
#pragma mark-Method one-(ID) hitTest: (cgpoint) point withevent: (uievent *) event{ UIView *hitview = [Super Hittest:point Withevent:event]; if (Hitview = = self) { return nil; } else { return hitview;} }
Let's examine it again:
Still this scenario, the user clicks Lgsecondview (click on the point not on the Buttonsecond, but in the Buttonfirst is very sad), the event processing flow is as follows:
1) Call UIWindow's Hittest:withevent: Method, Hittest:withevent: Method calls Pointinside:withevent: Method. At this point pointinside:withevent: Returns Yes, indicating that the touch event is above UIWindow.
2) go through the sub-view above UIWindow, that is, Self.view. The same is also called the Self.view Hittest:withevent: Method, Hittest:withevent: Method calls the Pointinside:withevent: method. At this point pointinside:withevent: Returns Yes, indicating that the touch event is above Self.view.
3) go through the sub-views on the Self.view, i.e. Lgfirstview and Lgsecondview. (Note: The traversal order of the child view is from top to bottom, which is traversing forward from the end of the subviews array).
4) So first call Lgsecondview's Hittest:withevent: Method, Hittest:withevent: Method calls Pointinside:withevent: Method. At this point pointinside:withevent: Returns Yes, indicating that the touch event is above Lgsecondview.
5) But, notice, here's a but, UIView *hitview = [Super Hittest:point withevent:event]; That's the code that works. If Hitview is Lgsecondview, then the click event is not handled. (This is not the same as Userinteractionenabled=no, Userinteractionenabled=no,lgsecondview on the Buttonsecond will not respond to click events.) )
6) This time will call Lgfirstview's hittest:withevent: Method, Hittest:withevent: Method will call Pointinside:withevent: method. At this point pointinside:withevent: Returns Yes, indicating that the touch event is above Lgfirstview.
7) then go through the lgfirstview above, that is, Buttonfirst, call Buttonfirst hittest:withevent: Method, Hittest:withevent: Method will call Pointinside: Withevent: Method. At this point pointinside:withevent: Returns Yes, indicating that the touch event is above Buttonfirst.
8) Then go through all the sub-views on the Buttonfirst, the result of all child views of the Hittest:withevent: methods are returned nil, indicating that click on the Buttonfirst,buttonfirst in response to the click Method.
Method Two
In LGSECONDVIEW.M
@interface Lgsecondview ()
@property (nonatomic, strong) Nsmutablearray *subcontrolsarray;
@end
@implementation Lgsecondview
-(ID) initWithFrame: (CGRect) frame
{
if (self = [Super Initwithframe:frame]) {
Self.subcontrolsarray = [Nsmutablearray array];
}
return self;
}
#pragma mark-Method two
-(void) Addsubview: (UIView *) view{
[Super Addsubview:view];
if ([View Iskindofclass:[uicontrol class]]) {
[Self.subcontrolsarray Addobject:view];
}
}
Set self does response action and self subviews Response action
-(BOOL) Pointinside: (cgpoint) point withevent: (Uievent *) event;
{
BOOL tonext = YES;
For (UIView *view in _subcontrolsarray) {
if (Cgrectcontainspoint (View.frame, point)) {
Tonext = NO;
Break
}
}
return!tonext;
}
The specific principle is not to be tired of the statement, we push it, you can also write down your thoughts sent to me.
There are also many ways to welcome you to write down your ideas to me. My number iOS development: Iosdevtip
Code: Hittestmaster
Scan two-dimensional code:
iOS User Click event Handling