Objective-C method call Process
Objective-C is a dynamic language. The dynamic words are mainly reflected in the dynamic search method when we call the method, and then the corresponding function address is called. The runtime is the entire objective-CProgramWith it, our program can run normally.
Nsobject is the base class of most classes in cocoa. It provides sequence calls, copy objects, and a framework that supports dynamic recognition during runtime.
In objective-C, each class object has an ISA pointer at the very beginning. This pointer points to a memory area, which contains two parts:
1. pointer to the parent class.
2. self-published methods.
With these two parts, the call process of objective-C methods can be run. When we call a method of an object, we will first find this method in the distribution table of the current class. If we cannot find the corresponding method, we will then look for this method in the parent class, and so on until the corresponding method is found. The flowchart is as follows:
You may think that if a class has a deep inheritance level and each time you call a function of the root class, you wouldn't have to perform many searches. In theory, it looks like this, But Runtime is not so silly. It will maintain a list of frequently called methods for every class (not an object, once called, it will be cached (the official website does not explicitly state the cache mechanism), so that the entire method call process will be more efficient when the program runs stably.
By studying the official objective-C runtime programming guide, we can find that all selector calls are converted to C type function calls. For example, we have created an object asample of type A, and then called its test method ([asample test]). During compilation, the compiler converts the call to the form of objc_send (asample, selector). runtime calls the function address corresponding to the test method implementation. The function parameters include two implicit Parameters Self and _ cmd. Self points to the object that calls the method, and _ cmd indicates the method to be called.
As mentioned above, nsobject provides a lot of traversal methods to interact with the runtime. There is a methodMethodforselector, through which we can directly obtain the function pointer corresponding to the specified method. Usually we can directly use the objective-C method to call the method, but sometimes the program may frequently call a method to improve efficiency. We can directly obtain the function address corresponding to the method and then directly call the function, thus reducing the time required for dynamic identification.
The following is an example:
// Define this method in the parent class -(Void ) Testmethod { // Nslog (@ "the implementation of basesample !!! "); Int A = 5 / 2.0f ; = ~ A ;} // Test method: Call 0.1 billion times using two methods respectively -( Void ) Test { Void (* Methodaddress )( ID , Sel); methodaddress = ( Void (*)( ID , Sel) [self methodforselector: @ selector (testmethod)]; nslog ( @" Invoke with method address start !!! " ); For ( Int I = 0 ; I < 100000000 ; ++I) {methodaddress (self, @ selector (testmethod);} nslog ( @" Invoke with method address finish !!! " ); Nslog ( @" Invoke with direct selector start !!! " ); For ( Int I = 0 ; I < 100000000 ; ++I) {[self testmethod];} nslog ( @" Invoke with direct selector finish !!! " );}
The running result is as follows:
The call time is as follows: it takes 0.151 seconds to call the function address, and 0.734 seconds to call the method directly. There is a gap in time, but it is very small. This also shows that the cache mechanism of Runtime is still very powerful.
When we call a method that does not exist, the program will crush and prompt"Unrecognized selector sent to instance 0 xxxxxxxAnd throw"Nsinvalidargumentexception. When a method that cannot be recognized by an object is called, runtime always searches for the class in the direction of the base class along the class inheritance relationship until the nsobject class. If the method still cannot be recognized, before the exception is thrown, the runtime gives us the last chance to "Remedy. It will call the forwardinvocation method first. If we want to capture the abnormal call of this method and pass it to other places, we can rewrite this method in the class. Nsobject's default implementation of the forwardinvocation method is to call the doesnotrecognizeselector method, while doesnotrecognizeselector directly throws an exception.
When forwardinvocation is called, an nsinvocation parameter is passed in. This parameter identifies the object of the called method and the called method, and encapsulates the call result of this method. When we override the forwardinvocation method, we must also rewrite the methodsignatureforselector method. This method returns a string that represents a method. For details about how to build it, see type encodings.
The following is a simple example of rewriting forwardinvocation:
# Pragma Mark- # Pragma Mark override forwardinvocation-(nsmethodsignature * ) Methodsignatureforselector :( SEL) aselector { If ([Self respondstoselector: aselector]) { Return [Super methodsignatureforselector: aselector];} Else { Return [Nsmethodsignature signaturewithobjctypes: " V @: " ] ;}} -( Void ) Forwardinvocation :( nsinvocation * ) Aninvocation {nslog ( @" Hello unreconginized selector! " );} // Call a non-existent method in init hello -(ID ) Initwithframe :( cgrect) frame {self = [Super initwithframe: frame]; If (Self ){ // Initialization code [Self Hello];} Return Self ;}
In the preceding example, an unidentifiable method call is intercepted, and a void-type method signature is created. When an unidentifiable method is called, a simple log is printed. Of course, it is best not to do this in the program, especially during development, most of the time we want to be able to detect such call errors as soon as possible.
Conclusion: The objective-C method calling process is basically finished. please correct me if you have any mistakes.
note: you are welcome to repost this article. For more information, see the source. At the same time, you are welcome to add QQ and look forward to discussing more questions with you.