The structure of the class
The class is divided into three parts
There are three things that are relevant to the method we call,
objc_calss
中cache_t cache
Methods the cacheclass_rw_t
中method_array_t methods
A list of methods for a two-dimensional arrayclass_ro_t
中method_list_t
A list of methods for a one-dimensional array
cache_t cache
The cache_t cache in objc_calss uses an array of hash tables (hash tables) to cache previously called methods, improving the speed of finding methods.
cache_t
_buckets
bucket_t
For an implementation of this method, see objc-cache.mm in the Runtime source code.
method_array_t methods
Class_rw_t method_array_T methods, a two-dimensional array containing primitive classes and classified methods, can be read and written, and when you add methods dynamically, you operate on this two-dimensional array.
method_list_t
Method_list_t in class_ro_t is an array containing only the methods of the original class, not the classified methods. Read-only cannot write.
method_t
The data structure of the method is as follows
struct method_t {
SEL name;
const char *types;
MethodListIMP imp;
}
Copy the code
- nameThe name of the method can be called selector. Can be achieved by
@selector()
和sel_registerName()
To obtain. - typesThe encoding of the method, that is, the type of the return value and argument. Return value Parameter 1 Parameter 2… Parameter N, a concatenated string of format codes.
@encode
The instruction can get the encoding character of a type. - Imp method concrete implementation, is a function pointer (function address)
IMP definition
Method call
Method call order: the system is to find the corresponding method from the method cache, then directly call the method in the cache, according to the IMP to call the method, no, then go to the method array traversal search, find the call and save to the method cache.
When we call a method, we actually convert the method into objc_msgSend. The execution process of objc_msgSend can be divided into three stages:
- Sending of messages
- Dynamic method resolution
- forward
Process of sending messages
Dynamic method resolution
+resolveInstanceMethod: +resolveInstanceMethod: +resolveInstanceMethodCopy the code
When we need a dynamic method resolver, we need to implement both methods and return YES.
class_getInstanceMethod
Method
class_addMethod
class_rw_t
Description: Add method imp to class object or metaclass object. It doesn’t matter what the property of this method is (class method or object method). The important thing is that when class_addMethod is used, you want this method to be an object method. Is added to the class_rw_t method of the class object; If you want it to be a class method, add it to the class_rw_t method of the metaclass object.
forward
If the method does not find related methods during the message sending phase and does not perform dynamic method resolution, the message forwarding phase is reached. The so-called message forwarding is that you can find other people or other methods to replace the message after it cannot be processed.
forwardingTargetForSelector
methodSignatureForSelector
forwardInvocation
- through
forwardingTargetForSelector
Fast forwarding is simple and convenient, but the disadvantage is that it can only forward the message caller
- (id)forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(test)) {
//return [[SomeClass alloc] init];
return [[NSObject alloc] init];
}
return [super forwardingTargetForSelector:aSelector];
}
Copy the code
- through
methodSignatureForSelector
和forwardInvocation
Standard forwarding, write up trouble point, need to write method signature and other information, but can be a large degree of custom method forwarding, can not find the method IMP when do any logic.
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(test) {// Note: this returns the signature of the method we want to forward, for example we are now forwardingtestMethod that's what returns istestMethod's signature / / 1. You can use methodSignatureForSelector: method requests from the instance instance method signature, or request from class class method signature. / / 2. You can also use instanceMethodSignatureForSelector: method from a class instance method signature / / here will use self into an infinite loop So can not be used If other methods with the same method, the self can be replaced by other classes / /return [self methodSignatureForSelector:aSelector];
//return[NSMethodSignature instanceMethodSignatureForSelector:aSelector]; //3. Enter a string directlyreturn [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return[super methodSignatureForSelector:aSelector]; } // The method will be forwarded to the method when the method signature is returned so there is plenty of room for the invocation. // The anInvocation has the message to forward the method, such as method caller /SEL/types/ parameters, etc. - (void)forwardInvocation:(NSInvocation *)anInvocation{ // SomeClass *obj = [[SomeClass alloc] init]; // Invocation. Target = obj; // Invoke invocation to save the invocation after the anInvocation invocation; // [anInvocation invokeWithTarget:[[SomeClass alloc] init]]; // This method is an empty method and will not report the error that the method can not find // can also submit the error message to the background statistics // for example, a method can not find submit to the background convenient line error collection.. Etc.}Copy the code
Overall flow chart
Methods exchange
Method Swizzling, occasionally used in development, replaces the system method with a custom method, or swaps the two methods.
- using
class_replaceMethod
Implementation of replacement methods - using
method_setImplementation
To set the IMP of a method directly - using
method_exchangeImplementations
Swap the implementation of the two methodsMethod
In theimp
.