In everyday development, we often encounter the headache of unrecognized selector. Often the program crashes not to say, but also not easy to locate the wrong location, so we today through the runtime dark magic to solve this problem.

Running the screenshot: We declare the test method in the Person_UnRecognized class, but we don’t implement the test method.

//
//  NSObject+UnRecognized.h
//  ObjectiveCDemo
//
//  Created by XiaoBai on 2022/3/28.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSObject (UnRecognized)


@end

NS_ASSUME_NONNULL_END
Copy the code
//NSObject+UnRecognized.m // // NSObject+UnRecognized.m // ObjectiveCDemo // // Created by XiaoBai on 2022/3/28. // #import "NSObject+UnRecognized.h" #import <objc/runtime.h> @implementation NSObject (UnRecognized) +(void)load { // Ensure that the load method is loaded only once static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ YH_swizzledMethod(self,@selector(methodSignatureForSelector:),@selector(YH_methodSignatureForSelector:)); YH_swizzledMethod(self,@selector(forwardInvocation:),@selector(YH_forwardInvocation:)); }); } - (NSMethodSignature *) YH_methodSignatureForSelector aSelector: (SEL) {/ / if the previous method can deal with, Then the original method call system if ([self respondsToSelector: aSelector]) {return [self YH_methodSignatureForSelector: aSelector]; } return [NSMethodSignature signatureWithObjCTypes:"v@:"]; } -(void)YH_forwardInvocation:(NSInvocation *)anInvocation { %@",anInvocation.target,NSStringFromSelector(anInvocation.selector)); // @param swizzledSelector // @param swizzledSelector // @param swizzledSelector // @param swizzledSelector YH_swizzledMethod(Class cls, SEL originSelector, SEL swizzledSelector) { Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector); /** * class_addMethod(Class _Nullable cls, * SEL _Nonnull name, * IMP _Nonnull imp, Const char * _Nullable types) * const char * _Nullable types) * BOOL res = class_addMethod(CLS, originSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); // If added successfully. Directly replace the implementation of the original method. if(res) { class_replaceMethod(cls, originSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); }else {// If the addition fails (perhaps because an implementation of the original method already exists). Method originMethod = class_getInstanceMethod(CLS, originSelector); method_exchangeImplementations(originMethod, swizzledMethod); } } @endCopy the code