Lattice 7: I understand runtime (2)

Source: Internet
Author: User

Message Sending ( Messaging )

8, the above is the runtime related to some data structure, then we look back at the beginning of the question:

How does the Objc_msgsend () function find the corresponding class in the process of execution, and find the corresponding method to implement it?

This is the process of message sending (messaging):

(1), for the description of the data structure of class above, the official documents are summarized in two parts: a pointer to its parent class and a method invocation table (the selector of all methods of this class and the associated table of the address where the code is implemented);

(2), when a message is sent to an object (that is, the object executes a method), runtime will find the class to which it belongs based on the object's Isa pointer, and find the corresponding selector in the method call table of the class. If it is not found, it will continue to find its parent class along the Super_class pointer of the class, and find the corresponding selector in the method call table of the parent class;

(3), after finding the corresponding selector, the code that executes these implementations is executed according to the address of the implementation code of the selector method. If it is not found, the message forwarding mechanism will be enabled, which will be described in detail later.

(4), so the implementation of a method of code, not at the time of compilation is OK, it is not until the time to call this method, only through the message sending mechanism, positioning to the implementation code of the method execution, so the method call and implementation is dynamic binding (dynamically bound);

(5), when executing the implementation code of the method, the Objc_msgsend () function will not only pass the parameters required to implement the code to it, but also two more hidden parameters: Self and _cmd. These two parameters are actually receiver and selector of Objc_msgsend (receiver, selector), on the Surface objc_msgsend () The function simply passes the parameters after receiver and selector to the implementation code of the method (if there are arguments later), and in fact it secretly transmits receiver and selector in, using self and _ in the implementation code of the method. Cmd These two parameters can be called to receiver and selector.

So why is it that when we write code for a method, we use "self" to invoke the object directly to the method call, which is passed in through this process;

(6), in order to improve the speed of sending messages, each time you look up a method call table, you will find a class of cache (see previous 7 (7)), the cache contains the usual method of selector and implementation of the corresponding code address, If you can find the corresponding selector in the cache, you can jump directly to the implementation code of the method and do not need to run the rest of the message sending process.

Judging whether the method is "commonly used" follows the principle that if a method is called once, it is likely to be called a second time, and this method will be added to the cache. If the program runs long enough to allow the cache to warm up enough (warn up), then the program will run faster than it was initially, and almost any method that needs to be called can be found in the cache.

(7), the official information sent by the flow chart is as follows:

Dynamic Method Parsing ( Dynamic Method Resolution ) and message forwarding (M essage Forwarding )

9, then there is a question is not discussed, that is, if the message is sent in the process of an accident, it will be how to deal with it? In fact, that is mentioned in 8 (3): If the message sent failed to find the corresponding method, then runtime will enable the message forwarding (messages forwarding) mechanism for processing.

First we know that under normal circumstances we will write the implementation code of the method in the @implementation of the class, when executing this method, the runtime will eventually bind to this implementation code and execute it, this is the normal process. If the corresponding implementation code is not found, then runtime will follow the following three steps to process the message:

(1), in fact, the runtime does not immediately start the message forwarding, the first runtime will do is the dynamic Method analysis (Resolution). It calls the class method of the current class +resolveinstancemethod: (process instance method) or +resolveclassmethod: (processing class method), to see if there is a method to add dynamic message in the method implementation, there is execution, and then continue the next process;

(2), if come to this step, is really to start the message forward. Runtime first forwards fast Forwarding, which invokes the current class's-(ID) Forwardingtargetforselector: method to see if there is any processing of this message forwarded to other classes. If there is a message forwarded to the corresponding processing class, none will continue the next process;

(3), the final runtime will complete the message forwarding (Normal Forwarding), it will first call-(Nsmethodsignature *) Methodsignatureforselector: Method, If the method returns a Nsmethodsignature object normally, it creates a Nsinvocation object that represents the message, which contains all the details related to the message, and then calls-(void) Forwardinvocation: Method for the full forwarding, if-(void) Forwardinvocation: The method has the relevant forwarding processing of this message, the message is forwarded to the corresponding other class for processing processing, if not, throw unrecognized selector sent to Instance or unrecognized selector sent to class exception information.

This is a complete message forwarding process.

10, we can verify the entire forwarding process through a demo of @samlaudev:

(1), first defines a message class, and defines an instance method in the class:

When this method is called:

will have the following output:

This is a normal method of execution;

(2), then we first verify the first step: Dynamic method parsing.

SendMessage-(void): The implementation code of the method is dropped, and the following methods are added:

This corresponds to the first step of processing, at this time-(void) SendMessage: The method has no normal implementation code, according to the first step, runtime will be in the +resolveinstancemethod: method to see if there is a dynamic addition-(void) SendMessage: Method implementation, at which time the output is run:

It is explained that runtime does perform dynamic method parsing.

(3), then we verify the second step, which is the first step of message forwarding: fast forwarding to other classes of processing.

You need to create a new class messageforwarding, and then define a-(void) message in the Messageforwarding class: Method:

Then go back to the message class, +resolveinstancemethod the previous step: method, add the following quick forward method:

This means that the message is quickly forwarded to the Messageforwarding object for processing, and the output is as follows:

Indicates that the runtime performs the first step of message forwarding;

(4), finally, we verify the third step of the process, that is, the second step of message forwarding: The message is fully forwarded to other classes of processing.

At this point we create a new class messagenormalforwading, and also define a-(void) message in the Messagenormalforwading class: Method:

Back to the message class, forwardingtargetforselector the second step-(ID): method, and add the following two methods:

Encapsulates the message into a Nsincocation object and then forwards it to the Messagenormalforwading class for processing. Post-Execution output:

Indicates that the runtime has performed the second step of message forwarding in a complete manner.

We have thus verified these three steps.

Dynamic parsing of class methods and type encodings

11, in 10 (2) of the first step, if the need to dynamically parse the method is a class method, what should be done?

We declare a class method + (void) Classsendmessage for the message class: And do not do any implementation, and then you need to add such a method to the message class to handle:

After executing the following code:

The output is as follows:

It is important to note that the first parameter in the Classsendmessage: method executes the Class_addmethod () function.

When we add an instance method, the first parameter of the Class_addmethod () function passes [self class], passing the current class, and when adding a class method, it is necessary to pass the class to which the [self class] belongs, the class to which the current class belongs, that is, the meta-class Class).

This is what we have discussed in the previous article, adding a method in the method_list of a class, which is an instance method of the class, that is, the method to add to the method_list of the Meta class to which the class belongs, the method that the instance of the meta-class can invoke, and the instance of the meta-class is the current class. Thus became the class method of this class.

12. Message forwarding enables a class to handle a number of methods that it could not otherwise handle by passing messages to other classes, seemingly simulating the effects of "multiple inheritance" by forwarding different messages to other classes to simulate the effects of inheriting from other classes. However, although message forwarding is similar to inheritance, some methods of nsobject can differentiate between the two, such as Respondstoselector: and Iskindofclass: Only for inheritance systems, not for forwarding chains.

13, there is another place to note: In the dynamic method parsing and full message forwarding in the relevant methods, there is a string: "[Email protected]*", the string is a type encoding, it will be the method in the message is summed up in a few strings to represent.

For example, in the case of message forwarding above, the method in the message is-(void) message:, so "[email protected]*" V means that the method return value of void,* means that the parameter is NSString type, @ is the hidden parameter self.

The hidden parameter is writable in the type code, so there is another hidden parameter _cmd, this type of code is written as "[email protected]:*" is also possible. Of course, it is no problem to write "v*" directly.

Reference Documentation:

Official documents

Https://github.com/samlaudev/RuntimeDemo

www.jianshu.com/p/25a319aee33d

Http://www.cocoachina.com/ios/20141105/10134.html

Http://www.cocoachina.com/ios/20141106/10150.html

Lattice 7: I understand runtime (2)

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.