I have a basic understanding of the responder chain concept encountered in iOS development in a previous blog, "iOS responder chain responder chain." But it is not enough to stay on the basis of understanding the concept. This blog will be a code case for a deeper understanding of the response chain. An example of this blog is uploaded to Https://github.com/chenyufeng1991/ResponderChain.
(1) First to say first Responder. The delivery process for responding to an event is to find the first responder. Here are a few ways:
Isfirstresponder: Determines whether the view is the first responder.
Canbecomefirstresponder: Determines whether the view can be the first responder.
Becomefirstresponder: Causes the view to be the first responder.
Resignfirstresponder: Cancels the first responder of the view.
Since the input box (Uitextfield) is a very convenient view to study the first response chain, here is a demo using the input box.
(2) There are two input boxes in the interface, respectively, the tag is set to 101,102, because the view set different tag can be used to distinguish between different view. Where the cursor is in the input box, then the input box is the first responder. Find the first responder in the following ways:
Set the view tag in the interface:
Self.view.tag = 100;self.nametextfield.tag = 101;self.passwordtextfield.tag = 102;
To find the first responder by traversing all the view in the interface:
Find the current page who is the first responder-(ibaction) Whoisfirstresponder: (ID) sender{ if ([Self.view Isfirstresponder]) { [self Showdialog:nil message:[nsstring stringwithformat:@ "First responder is%ld", (long) Self.view.tag]]; return; } For (UIView *view-self.view.subviews) { if ([view Isfirstresponder]) { [self showdialog:nil message : [NSString stringwithformat:@ "First responder is%ld", (long) View.tag]]; return;}}}
Let's say you put your cursor in the tag=101 input box, and the demo shows the following results:
。
(3) in our actual development, there is such a requirement, there may be multiple input boxes in the interface, but we want to set an input box as the current input, which can be done by setting the first responder. The following code is set input box 101 as the current input box:
Set Nametextfield 101 as the first responder-(ibaction) Setnametofirstresponder: (ID) sender{ if (![ Self.nametextfield Isfirstresponder]) { if ([Self.nametextfield Canbecomefirstresponder]) { [ Self.nametextfield Becomefirstresponder]; [Self Showdialog:nil message:@ "Set 101 as the first Responder"];}}
The implementation results are as follows:
。
(4) similar to the requirements above (3), we may need to cancel the first responder of the input box, which can use the following code:
Cancel Nametextfield 101 for first responder-(ibaction) Cancelnamefromfirstresponder: (ID) sender{ if ([Self.nametextfield Isfirstresponder]) { [Self.nametextfield resignfirstresponder]; [Self Showdialog:nil message:@ "Cancel 101 for first Responder"];} }
The implementation results are as follows:
。
(5) In fact, I want to know if the main view of the interface (Self.view) can become the first responder? The test code is as follows:
Set Self.view to First responder-(ibaction) Setselfviewtofirstresponder: (ID) sender{ if ([Self.view canbecomefirstresponder ]) { [Self.view becomefirstresponder]; if ([Self.view Isfirstresponder]) { [self showdialog:nil message:@ "set Self.view to First responder success"]; } else { [self showdialog:nil message:@ set Self.view to first responder failed '];} } else { [self showdialog:nil message:@ ' cannot set Self.view first Responder '];} }
The results are as follows:
。
It can be found that Self.view cannot be the first responder.
(6) At the same time I want to know whether the button can become the first responder, you can also use similar code as follows:
Determines whether a button can become the first response-(ibaction) Buttoncanbecomefirstresponder: (ID) sender{ if ([Self.judgethisbutton Canbecomefirstresponder]) { [Self.judgethisbutton becomefirstresponder]; if ([Self.judgethisbutton Isfirstresponder]) { [self showdialog:nil message:@ ' Set the button as the first responder success "]; } else { [self showdialog:nil message:@ ' Set this button to be the first responder failed '];} } else { [self showdialog:nil message:@ ' cannot set the button as the first Responder '];} }
The results are as follows:
。
It turns out that a button cannot be the first responder. If you want to test this feature of other view, you can use the above code.
(7) for a single click or touch operation, we print out its response chain. The main method used is nextresponder. I'm here by clicking the button and looking at the log logs.
The code is implemented as follows:
Get the response chain for the entire touch event-(ibaction) Getnextresponder: (ID) sender{ uiresponder *responder = sender; NSLog (@ "\n%@\n", [Responder class]); while (responder! = nil) { responder = [responder Nextresponder]; NSLog (@ "\n%@\n", [Responder Class]);} }
Log prints the following results:
。
Here you can see that the response chain is passed in order: uibutton-->uiview-->fourthviewcontroller-->uitabbarcontroller-->uitransitionview-- >uiwindow-->uiapplication-->appdelegate. The output is the same as we mentioned in our concept.
(8) If we want to perform certain actions when the response chain is passed to a node in the tree, the following code can be executed:
-(Ibaction) Captureevent: (ID) sender{ uiresponder *responder = sender; while (responder! = nil) { if ([Responder Iskindofclass:[self class]]) { NSLog (@ "event passed to the class VC, you can do the appropriate action" ); } if ([Responder Iskindofclass:[uiapplication class]]) { NSLog (@ "event passed to UIApplication, you can do the appropriate action"); } responder = [responder Nextresponder]; }}
The output results are as follows:
。
(9) In the touch event, there is touchesbegan,touchescancelled ... These several methods. These methods are Uiresponder instance methods, and the interface can be interactive view and VC, the basic is inherited from Uiresponder, so there will be Touchesbegan method. When we rewrite this method in both APPDELEGATE.M and VC, we test it by touching the screen, and when we find that the response chain is passed to the VC, the default is no longer passed to appdelegate. To invoke Appdelegate, you can use super to make an explicit call.
Summary, using the response chain, you can have multiple objects on one chain respond to the same event. 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 from Uiresponder can become a node in this N-fork tree. When a leaf node becomes the highest responder, the chain is the current responder chain from the leaf node to the parent node, starting with a chain of traces. The responder chain distributes the uievent captured by the system to the Uitouch from the leaf node layer, during which you can choose to stop distribution or continue to distribute upward. One sentence is the process of passing events.
iOS development--deep understanding of the response chain (Responder Chain) and code examples