The data structure
1. objc_object
All objects (id types) normally used in the OC correspond to the objc_Object structure in the Runtime.
Objc_object structure:
- isa_t
- Related to ISA operation
- Weak reference correlation
- Associated object correlation
- Memory management related
2. objc_class
The Class used in OC corresponds to objc_class in Runtime. Inherits from objc_Object. Class is also an object, called a Class object.
Objc_class structure:
Class superClass;
Pointer to the parent classcache_t cache;
Method caching, which is used during messagingclass_data_bits_t bits;
Class defines protocols, properties, and methods
3. Isa pointer
- Pointer ISA: The value of ISA represents the address of Class.
- Nonpointer ISA: The worthy part of isa represents the address of Class.
In the case of pointer addressing, such as on 64-bit devices, where 30 or 40 bits are enough to ensure that all Class addresses are found, a non-pointer ISA can store something else to save memory.
Isa to
- With respect to objects, they refer to class objects.
- For class objects, they refer to metaclass objects.
- Isa Pointers to all metaclass objects point to the root metaclass object, including the root metaclass itself.
Graph LR A [example] -- > | isa | B [Class] -- > B | isa | C [MetaClass]
4. cache_t
Object methods are called by the compiler for method lookups. The compiler caches frequently lookups methods and the next time they are lookups, which saves time and speeds up lookups. This is where Cache_t comes in.
- Used to quickly find method execution functions
- Is an incrementally extensible hash table structure
- It is the best application of locality principle
Can be interpreted as a Hash table full of bucket_t structures. Bucket_t contains two main member variables: key and IMP. Key corresponds to SEL in OC, which is a string representing the name of the method. IMP is a pointer to the start of a method implementation.
5. class_data_bits_t
- Class_data_bits_t encapsulates class_rw_t.
- Class_rw_t represents class-related read and write information and encapsulates class_ro_t.
- Class_ro_t represents read-only information about a class.
Rw /ro in class_rw_t/class_ro_t stands for readwrite/readonly
6. class_rw_t
- class_ro_t
- Properties: properties
- Separate protocols: agreement
- Methods: List of methods (usually added by category)
Properties, protocols, and methods in the class_rw_t structure are two-dimensional arrays that inherit from list_array_TT.
7. class_ro_t
- Name: name of the class
- Ivars: member variable
- Properties: properties
- Separate protocols: agreement
- MethodList: list of methods (originally defined methods)
Ivars, properties, protocols, methodList in the class_ro_t structure are all one-dimensional arrays.
8. method_t
SEL name;
The name of the functionconst char* types;
Return values and parameters (Type Encodings)IMP imp;
Pointer to the starting address of the function implementation
A function has four elements: name, return value, parameter, and function body.
The messaging
1. Object, class object, metaclass object
The instance object is an objc_Object data structure; Class objects and metaclass objects are both part of the objC_Class data structure, which in turn inherits from the ObjC_Object data structure. An instance object can find its class object through the ISA pointer, which stores information such as the list of instance methods. A class object can find its metaclass object through the ISA pointer. Metaclass objects store information such as the list of class methods. The superClass pointer to the root object points to nil; Isa Pointers to all metaclass objects point to the root metaclass, including the root metaclass itself. The superClass pointer to the root metaclass object points to the root metaclass object;
2. Instance method messaging
- When we call the instance method, the system first finds its class object based on the isa pointer of the current instance.
- The cache is searched in the class object, and then the method list is iterated to find the method implementation with the same name.
- If not, the method list of the parent class will be iterated according to the superClass point of the class object until the root class object.
- If the method is not found all the way to the root object, the message forwarding process enters.
3. Class method messaging
- When we call a class method, the system finds its metaclass object through its ISA pointer;
- In the metaclass object, the cache is first searched, and then the method list is iterated to find the method implementation with the same name.
- If not, the method list of the parent metaclass will be iterated according to the superClass pointer of the metaclass object until the root metaclass object.
- If the method is not found in the root metaclass because the superClass of the root metaclass refers to the root metaclass, then the instance method implementation of the same name will be found in the root metaclass.
- If there is an instance method of the same name in the root object, that instance method is executed;
- If there is no instance method of the same name in the root class object, the message forwarding process enters.
4. [self class], [super class]
- [self class] ==> objc_msgSend(self, @selector(class))
- [super class] ==> objc_msgSendSuper(super, @selector(class))
Although super is passed in the Runtime when the super method is called, it is actually a structure of type objc_super that contains a receiver object that refers to the current object, not its parent. So [self class] and [super class] both return the current class of the object. The difference is that super skips the method list of the current class by iterating through @selector(class), and starts with the method list of the parent class.
5. Cache lookup cache_t
According to the given method selector (SEL), through the hash search, to map the bucket_t location in the array, and finally obtain the method implementation (IMP).
Hash search: The hash function algorithm calculates a value for a given Key. The value calculated is the index position of the corresponding element in the array for the Key.
6. Find in the current class
- For sorted lists, binary search algorithm is used to search.
- For unsorted lists, use the general traversal method to find.
7. Message forwarding process
-
ResolveInstanceMethod: / resolveClassMethod: first, the system will callback the method, the Instance says the message forwarding, Class Instance methods said Class methods forward. The argument is a method selector (SEL), and the return value is a BOOL indicating whether the system should resolve the method implementation.
-
ForwardingTargetForSeLector: when step 1 method to return NO, system will callback the method. The argument is also a method selector (SEL) that returns an ID indicating which object should process the message.
-
MethodSignatureForSelector: if the forward the method of step 2 is not specified, the system will call the method, and forward one last chance. The argument is a method selector (SEL), and the return value is an object of type methodSignature, which encapsulates the type of the method selector return value as well as the number of arguments and parameter types. If the method signature is returned, the forwardInvocation: method is called; If forwardInvocation: unable to process this message, or methodSignatureForSelector: returns nil, causes a Crash.
Graph LR A [resolveInstanceMethod:] -- > | return NO [forwardingTargetForSeLector:] -- > A | B | returns YES | F/message processed B - > | returns nil | C [methodSignatureForSelector:] -- > | | back forward target F C - > | | D return method signature/forwardInvocation: C - > | returns nil | E [news cannot handle] D -- -- -- -- > > E D F
8. Dynamic method parsing
- Dynamic runtime languages defer function decisions to runtime.
- Compile time Languages make function decisions at compile time.
When we identify a property as@dynamic
When, it means that the compiler does not need to generate the concrete implementation of the property get/set method for us at compile time, but to add the concrete implementation when we specifically call the property get/set method at run time.
9. Can I add instance variables to the compiled class?
Can’t. Before the class is compiled, the instance variables are laid out and stored in class_ro_T, which is read-only.
10. Can I add instance variables to dynamically added classes?
You can. In the process of dynamically adding classes, instance variables can be added as long as they are prior to registration.