Responder's not a mystery. ———— iOS user responder chain complete anatomy

Source: Internet
Author: User
Tags uicontrol

The main thrust of this article to share with you is the various scenarios in which iOS captures user events, as well as some special events in the internal encapsulation.

We start from the UIButton, UIButton everyone use too much, his special place lies in its built-in ordinary default/highlight highlighted/Select selected/can be enabled in several states (Uicontrolstate). The second is that the following user events have been encapsulated within the SDK for us:

The most common is the touch up inside event, which he represents: the user presses within the button area and also releases within the button area.

Key: Press and release to trigger this method, that is, the correct action is pressed once, and releasing once only triggers this event once. Unlike the touch Drag inside and other methods do not need to loosen this process, up into Drag, in fact, we can understand that the SDK in the packaging when the principle and uitouchevent is a reason, the first word touch represents the press (began) The second word up stands for release (Ended), and drag represents drag (Moved). The Touchmoved method is triggered many times in a full touch, so the touch Drag inside method is triggered until the user's hand is released.

These are the events that UIButton has encapsulated, and UIButton inherits from Uicontrol. Uicontrol also inherits from UIView. The controls that we can normally use with these encapsulated events are subclasses of Uicontrol. Then there is no internal event for the parent class UIView.

We often use UIView to write our own uitouchevent. For example, the following 3 methods are implemented directly in a view/viewcontroller:

[CPP]View PlainCopyprint?
  1. -(void) Touchesbegan: (Nsset *) touches withevent: (Uievent *) event
  2. {
  3. }
  4. -(void) touchesmoved: (Nsset *) touches withevent: (Uievent *) event
  5. {
  6. }
  7. -(void) touchesended: (Nsset *) touches withevent: (Uievent *) event
  8. {
  9. }
  10. -(void) touchescancelled: (Nsset *) touches withevent: (Uievent *) event
  11. {
  12. }

We use a lot of it, but do you know who is the example of these 4 methods? If you say it is uiview, then why we can use it in the Uiviewcontroller, they are not the inheritance relationship.

Note that these 4 instance methods come from the common parent class of UIView and Uiviewcontroller: Uiresponder. It is the protagonist of our day.

Basically all the graphical interfaces we can see are inherited from Uiresponder, so, why is it sacred?

Uiresponder, the so-called parent of many views, is in charge of the user's Operation event distribution. Without him, how does our capacitive screen respond to the user's actions by passing them to our view?

Let's first look at the concept of the responder chain in iOS:

Each application has a responder chain, our view structure is an n-fork tree (a view can have multiple sub-views, a child view has only one parent view at a time), and every object that inherits Uiresponder can play a node in this N-fork tree. When the leaf node becomes the highest responder, starting from this leaf node to its parent node begins to chase a chain, then for this one leaf node, this chain is the current responder chain. The responder chain distributes the uievent captured by the system to the Uitouch from the leaf node, where you can choose to stop distribution, or you can choose to continue distributing downward.

Example:

I created a new project with the Singleview template, which has only one uiviewcontroller on the main window and a button on the view. This is the structure of the N-fork Tree of all uiresponder subclasses in this project:

Then he does not look like the N-fork tree, but does not mean that the person is not a n-fork tree, when our project is complex, can this view have multiple UIButton nodes? So he is a tree.

In fact, we have to write this tree complete, should also be counted on the UIButton Uilabel and Uiimageview, because they are also uireponder subclasses. This is not the first consideration here.

For UIButton, if he is a leaf node at this point, then we are responding to his response chain, and his former responder should be the view of our controller (the leaf nodes in the tree will always be more preferentially distributed than the parent node, but it does not mean that he can respond first in time, Let's talk about why below). So we tried to print the button's Nextreponder object anywhere. The Nextresponder object is an instance method of the Uireponder class that returns the previous responder instance of any object in the tree:

[CPP]View PlainCopyprint?
    1. NSLog (@"%@", _testbutton.nextresponder);


Console output message:

2013-09-21 03:40:25.989 response chain [614:60b] <UIView:0x16555e10; frame = (0 0; 568); autoresize = rm+bm; layer = <calayer:0x1 6555e70>>

We can tell by the size of this uiview that he is the UIView in our only controller.

Next we print out who the next responder of this uiview is:

[CPP]View PlainCopyprint?
    1. NSLog (@"%@", _testbutton.nextresponder.nextresponder);


Output:

2013-09-21 03:45:03.914 response chain [621:60b] <RSViewController:0x15da0e30>

Look, then add a nextresponder:

2013-09-21 03:50:49.428 response chain [669:60b] (NULL)

Why is there no father here Viewcontroller?

Note that this code is written in Viewdidload, and we know the life cycle of this method is relatively early, so we can write it somewhere else or delay it for a while, both ways to get the results ( It can be inferred that the construction of our responder tree is done in the Viewdidload cycle, which merges the responder subtree of the current instance into our entire root tree:

2013-09-21 03:53:47.304 response chain [681:60b] <UIWindow:0x14e24200; frame = (0 0; 568); gesturerecognizers = <nsarray:0x14e 242e0>; Layer = <UIWindowLayer:0x14e244a0>>

and continue on to the chase:

[CPP]View PlainCopyprint?
    1. Double delayinseconds = 2.0;
    2. dispatch_time_t poptime = Dispatch_time (Dispatch_time_now, (int64_t) (Delayinseconds * nsec_per_sec));
    3. Dispatch_after (Poptime, Dispatch_get_main_queue (), ^ (void) {
    4. NSLog (@"%@", _testbutton.nextresponder.nextresponder.nextresponder.nextresponder);
    5. });

2013-09-21 03:56:22.043 response chain [690:60b] <UIApplication:0x15659c00>

Add one more:

2013-09-21 03:56:51.186 response chain [696:60b] <RSAppDelegate:0x16663520>

So does our appdelegate still have a parent node?

2013-09-21 03:57:22.588 response chain [706:60b] (NULL)

No, note that an event that is distributed from a leaf node can only be distributed to our appdelegate!

This tree structure is especially important in our project, for a chestnut, if we want to rewrite Uitouchevent's 4 methods in a view, and not affect his parent view to respond to these events, pay attention to the way you rewrite them. For example, we rewrite Touchbegan in Viewcontroller as follows:

[CPP]View PlainCopyprint?
    1. -(void) Touchesbegan: (Nsset *) touches withevent: (Uievent *) event
    2. {
    3. NSLog (@"Viewcontroller received touch event");
    4. }


The same paragraph is also written in Appdelegate:

[CPP]View PlainCopyprint?
    1. -(void) Touchesbegan: (Nsset *) touches withevent: (Uievent *) event
    2. {
    3. NSLog (@"Appdelegate received touch event");
    4. }



So who is being triggered?

2013-09-21 04:02:49.405 response chain [743:60b] Viewcontroller receive touch events

This is a good understanding, I have just said, Viewcontroller is obviously the appdelegate child node, he has the priority of event distribution. What if we want to trigger all two places? Here's a super-bit:

[CPP]View PlainCopyprint?
    1. -(void) Touchesbegan: (Nsset *) touches withevent: (Uievent *) event
    2. {
    3. [Super Touchesbegan:touches Withevent:event];
    4. NSLog (@"Viewcontroller received touch event");
    5. }

Output:

2013-09-21 04:07:26.206 response chain [749:60b] appdelegate receive touch events

2013-09-21 04:07:26.208 response chain [749:60b] Viewcontroller receive touch events

Pay attention to the time stamp, appdelegate Although the priority level is inferior to viewcontroller, but he responds to the time above Viewcontroller 0.002 seconds earlier, I tried several times here, all is the difference 0.002 seconds.

So let's analyze how the responder chain works here:

The user finger touches the uiview, because we did not rewrite UIView's uitouchevent, so he and super executed the same, will continue to distribute the event to Uiviewcontroller;

Uiviewcontroller's Touchbegan was rewritten by us, and if we weren't super, then we'd write the response code here. The incident will not continue to be distributed here. It is conceivable that uiviewcontroller ancestor node: Uiwindow,uiapplication,appdelegate is not authorized to be distributed this event.

If we super Touchbegan, then this touch event is

Viewcontroller distributed to UIWindow,

UIWindow then distributed to UIApplication,

The uiapplication is distributed to Appdelegate,

So we captured this event in the Touchbegan method of Viewcontroller and Appdelegate.

You should have a good understanding of this responder tree here, right?

Let's talk about the first responder, and the event distribution on UIButton.

Responder's not a mystery. ———— iOS user responder chain complete anatomy

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.