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_calsscache_t cacheMethods the cache
  • class_rw_tmethod_array_t methodsA list of methods for a two-dimensional array
  • class_ro_tmethod_list_tA 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.@encodeThe 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

  • throughforwardingTargetForSelectorFast 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
  • throughmethodSignatureForSelectorforwardInvocationStandard 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.

  • usingclass_replaceMethodImplementation of replacement methods
  • usingmethod_setImplementationTo set the IMP of a method directly
  • usingmethod_exchangeImplementationsSwap the implementation of the two methodsMethodIn theimp.