Function call for developing RunTime in iOS
The article is from Xiao binlang's iOS blog. He has always thought that the blog UI of csdn is not very nice and he is not very good at reading blogs, so he set up a blog by himself. You are welcome to visit my blog at the link. You are also welcome to join the QQ Group to discuss iOS technology issues.
After more than two months of interviews, the work was settled. During the interviews over the past two months, I found that many underlying things are very important to large companies. For example, RunLoop, RunTime, and Block. This article mainly introduces the function calling mechanism in RunTime. The knowledge points are in-depth and reflect the competence in the interview process.
1. function call in Objective-C
For C language, function calls are directly converted by the compiler. during compilation, the program starts to look for the function to be executed (C language function call principle ). In OC, function calling is called message sending. During compilation, the program does not search for the function to be executed. It must wait until the program runs.
Example: in C language, only one function is declared and not implemented. Call this function elsewhere. An error is reported during compilation (the function to be executed is found during C language compilation, so the error is not found ). In the same case, no error is reported in OC, and only an error is reported during running. (Find the function to be executed only when the OC runs)
2. Underlying implementation of Objective-C function calls
Objective-C
The reason why you can find the function to be executed during running is mainly due to the runTime SDK. Let's take a look.Objective-C
How to make the program have runtime characteristics.
There isobjc_msgSend()
Method
OBJC_EXPORT id objc_msgSend(id self, SEL op, ...)
When we write down a line of code[obj doSth];
During compilation, the compiler will convert our code
objc_msgSend(obj,@selector(doSth));
objc_msgSend()
The method implements function search and matching. The following describes its principle:
- Based on the object
obj
Find the function list stored in the object classmethodLists
.
- Then, according to SEL
@selector(doSth)
InmethodLists
Find the corresponding function pointer inmethod_imp
.
- According to the function pointer
method_imp
Call the response function. 3. Implementation Details of objc_msgSendWe just briefly introducedobjc_msgSend()
For more information, seeobjc_msgSend
Is implemented.
First, there is an isa attribute under any NSObject object, pointing to the correspondingClass
Class
@interface NSObject
{ Class isa OBJC_ISA_AVAILABILITY;}
You can obtain the correspondingClass
. Let's take a look.Class
Typedef struct objc_class * Class; struct objc_class {Class isa; // points to metaclass Class superclass; // points to parent Class const char * name; // Class name uint32_t version; // Class version information uint32_t info; // some identification information, indicating whether it is a common Class or metaclass uint32_t instance_size; // The instance variable size of the class (including the instance variables inherited from the parent class); struct old_ivar_list * ivars; // The information of the member variables in the class struct old_method_list ** methodLists; the method list Cache in the class; the cache of the search method, used to improve efficiency struct old_protocol_list * protocols; // store the protocols that this class complies}
We can see from the above CodeClass
Is a struct pointer pointingobjc_class
Struct. Inobjc_class
Stored inmethodLists
Method list. ThereforeClass
We can findmethodLists
Next let's take a look at howmethodLists
Find the corresponding function pointer
Struct old_method_list {void * obsolete; // discarded attribute int method_count; // number of methods/* variable length structure */struct old_method method_list [1]; first address of the method }; struct old_method {SEL method_name; // SEL char * method_types corresponding to the method; // method type IMP method_imp; // function pointer corresponding to the method };
Forold_method_list
Struct, which storesold_method
The number of methods and the first address of the method. We can regard it as a variable-lengthold_method
Array.
At first, I don't understand whymethod_list[1]
How can the array size be 1? Later I figured out that because the array size is variable, different classes correspond to different methods. Therefore, only the first address is stored during definition, and the length is extended during actual use.
Forold_method
Struct, which consists of three members: SEL, type, and IMP. Therefore, we only needmethod_list
Foundold_method
You can get the function pointer IMP. The following is the search code:
static inline old_method *_findMethodInList(old_method_list * mlist, SEL sel) { int i; if (!mlist) return nil; for (i = 0; i < mlist->method_count; i++) { old_method *m = &mlist->method_list[i]; if (m->method_name == sel) { return m; } } return nil;}
- The lookup function is an inline function.
old_method_list
AndSEL
, Returnold_method
- First
old_method_list
Array is empty. If it is null, nil is returned.
- Traversal
old_method_list
Array, accordingSEL
Match, findold_method
4. function call Performance OptimizationThe above section describes the basic process of function calling. After reading the above sections, you may be confused:Objective-C
Function calls are so complex, will it lead to very slow running? After all, every time you call a function, you have to go through so many processes.
Don't worry. In fact, Apple has made some performance optimization during the call process, so that it does not call much more than the C language. Next, let's take a look at the performance optimizations:
4.1 Use of SELYou may have long been confused.SEL
,SEL
What is it?
/// An opaque type that represents a method selector.typedef struct objc_selector *SEL;
Apple's official explanation of SEL is: an opaque type, which represents a method selector.
SEL is actually an int type address, pointing to the name of the stored method. For each class, a special empty space is allocated. The method name in the special storage class, SEL is the address pointing to the corresponding method name. Because the method name string is unique, SEL is also unique.
Why not use SEL instead of the method name? This problem does not find more official information. I personally think that because the method name is a string and SEL is an int type, int type is more convenient and more efficient (especially when the comparison is equal, string comparison is much less efficient than int)
4.2 Use of cacheLet's take a closer look at the function call process:
obj->isa->methodListsold_method->method_imp
- Because
isa
Yesobj
Member variables,methodLists
Yesisa
So useobj
Can be obtained directlymethodLists
- Because
method_imp
Yesold_method
So useold_method
Can be obtained directlymethod_imp
Therefore, the main time consumed in the function call process ismethodLists
Searchold_method
.
cache
It is used to optimize the search process.
We cancache
As a hash table,key
YesSEL
,Value
Yesold_method
. From this we can see thatcache
Searchold_method
Relatively simple and efficient.
SlavemethodLists
Searchold_method
The real process is divided into the following two steps:
- Pass
SEL
Incache
Searchold_method
If no result is found, 2 is returned. If no result is found, 2 is returned.
- In
methodLists
Searchold_method
.old_method
Insertcache
To facilitate next search and then returnold_method
It can be seen that the first time a function is called, it will be slow becausecache
Without this function, the second call will be very fast.
SummaryThis article focuses onObjective-C
In the function call process, other irrelevant things are ignored, suchobjc_class
Other member variables in the struct are used. If no function is found in this class, how can this function be searched in the parent class? What if no function is found? I may introduce these questions in the future. Now I want to write them here. If you want to know, you can ask a question in the comment area or add a QQ Group for discussion. If you have any objection, you can also tell me