Objective-C's total Runtime (1) message mechanism [conversion], objective-cruntime
RunTime is short for RunTime. It is the mechanism of the system when it is running, the most important of which is the message mechanism. For C language, function calls determine which function to call during compilation (for details about C language function calls, refer to here ). After the compilation is complete, it is executed in sequence without any ambiguity. OC function call is used to send messages. It is a dynamic call process. During compilation, you cannot decide which function to call. (It turns out that in the compilation phase, OC can call any function. Even if this function is not implemented, no error will be reported if it has been declared. C language reports an error in the compilation phase ). The corresponding function is called only when the function is running.
So how does OC implement dynamic calling? Next let's take a look at the OC's secret of dynamic calling by sending messages. Assume that the following code is written in OC:
Obj is an object and makeText is a function name. For such a simple call. During compilation, RunTime will convert the above Code
1 |
objc_msgSend(obj,@selector(makeText)); |
First, let's take a look at the object obj. In iOS, obj inherits from NSObject.
123 |
@interface NSObject <nsobject> { Class isa OBJC_ISA_AVAILABILITY; }</nsobject> |
There is a Class isa pointer in NSObjcet. Then let's look at the Class:
1234567891011121314 |
typedef struct objc_class *Class; struct objc_class { Class isa; // Point to metaclass Class super_class ; // Point to its parent class const char *name ; // Class Name long version ; // Class version information. The default initialization value is 0. You can use the runtime functions class_setVersion and class_getVersion to modify and read long info; // Some identification information. For example, CLS_CLASS (0x1L) indicates that the class is a common class, including object methods and member variables. CLS_META (0x2L) indicates that the class is metaclass, including class methods; long instance_size ; // Instance variable size of the class (including instance variables inherited from the parent class ); struct objc_ivar_list *ivars; // Address used to store each member variable struct objc_method_list **methodLists ; // It is related to some flag bits of info, such as CLS_CLASS (0x1L). It stores object methods, such as CLS_META (0x2L; struct objc_cache *cache; // Pointer to the recently used method to improve efficiency; struct objc_protocol_list *protocols; // Store the protocols that this class complies } |
As we can see, there are many things in a Class. Let me explain them one by one:
Class isa: Point to metaclass, which is a static Class. Generally, isa in an Obj object points to a common Class, which stores common member variables and Methods starting ), the isa pointer in a common Class points to a static Class. The static Class stores static member variables and Class methods (Methods starting with "+ ).
Class super_class: points to the parent Class. If this Class is the root Class, it is NULL.
The following image describes the inheritance relationship between classes and objects:
Note:: All isa pointers in metaclass point to metaclass. However, metaclass points to itself. Root metaclass is generated by inheriting the Root class. It is consistent with the root class struct, that is, the structure mentioned above. The difference is that the isa pointer of Root metaclass points to itself.
Other members in the Class will not be explained too much here. Let's take a look:
@ Selector (makeText): This is a SEL method selector. SEL is mainly used to quickly find the function pointer of the corresponding method through the method name (makeText), and then call its function number. SEL itself is an Int type address, which stores the method name. For a class. Each method corresponds to a SEL. Therefore, there cannot be two methods with the same name in the iOS class. Even if the parameter type is different, because SEL is generated based on the method name, the same method name can only correspond to one SEL.
Next, let's take a look at how to dynamically find the corresponding method after a specific message is sent.
First, the compiler converts the Code [obj makeText]; To objc_msgSend (obj, @ selector (makeText); In the objc_msgSend function. First, find the class corresponding to obj through the isa pointer of obj. In the Class, first go to the cache and use SEL to find the corresponding function method (in the cache, the method list is stored using SEL as the key through the hash table, which can improve the function search speed ), if not. Search in methodList again. If no value is found in methodlist, search in superClass. If it can be found, add the method to the cache for the next search, and use the function pointer in the method to jump to the corresponding function for execution.