“This is the 25th day of my participation in the First Challenge 2022. For details: First Challenge 2022.”
1. Send messages
If the receiver is nil, exit the receiver directly. If the receiver is not null, find the method in the receiverClass cache. If the receiver is found, call the method to end the search. If not found, the method is searched from the receiverClass class_rw_t method array (if the methods in the method list are sorted by dichotomy, otherwise, the method is searched one by one). If found, the method is called and the search ends. The method is cached in the receiverClass cache. If no method is found, the method is searched from the SuperClass cache. If no method is found, the method is called, the search ends, and the method is cached in the receiverClass cache. If found, call the method, end the search, and cache the method to the receiverClass cache. If not found, continue looking for the superclass. (cache/superclass_rw_t), if not, the second phase, dynamic message parsing, is entered
2. Dynamic method parsing
Check whether there has been dynamic resolution before. If not, call +resolveInstanceMethod: or +resolveClassMethod: to resolve the method dynamically, and then mark it as dynamic resolution. After that, send the message
After dynamic parsing, the “message sending process” is reworked, starting with the “find method in the Cache of reserveClass” step
If no method can be found, dynamic method parsing will be entered again. At this time, since dynamic parsing has been done before, message forwarding will be entered into the third stage.
// Object method
-(void)other{
NSLog(@"%s",__func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
if (sel = = @selector(study)) {
Method method = class_getInstanceMethod(self.@selector(other));
class_addMethod(self, sel, method_getImplementation(method), method_getTypeEncoding(method));
}
return [super resolveInstanceMethod:sel];
}
/ / class methods
+(void)other2{
NSLog(@"%s",__func__);
}
+ (BOOL)resolveClassMethod:(SEL)sel
{
if (sel = = @selector(work)) {
Method method = class_getClassMethod(object_getClass(self), @selector(other2));
class_addMethod(object_getClass(self), sel, method_getImplementation(method), method_getTypeEncoding(method));
return YES;
}
return [super resolveClassMethod:sel];
}
Copy the code
3. Forwarding messages
If step 2 does not perform incoming message forwarding phase, called forwardingTargetForSelector, if the return value is nil, objc_msgSend (return value, SEL), if the return value is nil, Call the methodsignatureForSelector: method, if you call this method after the return value is nil, will call doseNotRecognizeSelector: method of the classic mistake. If the return value is not empty (method signature) then the forwardInvocation: method is called and you can do whatever you want in the method.
/ / forwardingTargetForSelector the return value is nil, forwarded to other people who have the method of the object
-(id)forwardingTargetForSelector:(SEL)aSelector
{
if (aSelector = = @selector(study)) {
// Message forwarding, with the MJCat object in place of its method, provided that MJCat also has a study method
return [[MJCat alloc]init];
}
return [super forwardingTargetForSelector:aSelector];
}
// if the return value is nil, forwardInvocation
// Return the method signature
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
if (aSelector = = @selector(study)) {
//v16@0:8 = void xxx (self,_cmd)
return [NSMethodSignature signatureWithObjCTypes:"v16@0:8"];
}
return [super methodSignatureForSelector:aSelector];
}
//NSInvocation - Method invocation
// Method name -anInvocation. Selector
// Method invocation -anInvocation. Target
// Method Parameter - anInvocation getArgument: atIndex:
- (void)forwardInvocation:(NSInvocation *)anInvocation{
// Sets the method caller
[anInvocation invokeWithTarget:[[MJCat alloc]init]];
}
Copy the code
Supplement:
Class methods can also implement message forwarding, but with '+ (id)forwardingTargetForSelector:(SEL) aSelector ` function// Message forwarding for class methods,
[MJStudent test];
Copy the code