通过类名调用被分类覆盖的原方法

通过类名调用被分类覆盖的原方法

在分类中重写方法后,会将原方法进行覆盖。若想继续执行原方法则可通过方法列表和方法指针找到原方法

- (void)viewDidLoad {
    [super viewDidLoad];
    Class currentClass = [TestClass class];
    TestClass *my = [[TestClass alloc] init];
    [my printName];
    if (currentClass) {
        unsigned int methodCount;
        Method *methodList = class_copyMethodList(currentClass, &methodCount);
        IMP lastImp = NULL;
        SEL lastSel = NULL;
        for (NSInteger i = 0; i < methodCount; i++) {
            Method method = methodList[i];
            NSString *methodName = [NSString stringWithCString:sel_getName(method_getName(method))
                                            encoding:NSUTF8StringEncoding];
            if ([@"printName" isEqualToString:methodName]) {
                lastImp = method_getImplementation(method);
                lastSel = method_getName(method);
                // 按照方法列表遍历(分类的方法在原方法的前面),如果第一次拿到的printName就break出去,则获取的是分类的方法。如果继续遍历,则拿到的最后一个就是类本身的原方法。
                // break;
            } //lastSel 是原方法的编码
        }
        typedef void (*fn)(id,SEL);

        if (lastImp != NULL) {
            fn f = (fn)lastImp;
            f(my, lastSel); // 执行方法
        }
        free(methodList);       

    }
}

TestClass.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface TestClass : NSObject
- (void)printName;
@end

NS_ASSUME_NONNULL_END

TestClass.m

#import "TestClass.h"

@implementation TestClass
- (void)printName{
    NSLog(@"printName%s==TestClass",__func__);
}
@end

TestClass+addNewMethod.h

#import "TestClass.h"

NS_ASSUME_NONNULL_BEGIN

@interface TestClass (addNewMethod)
- (void)printName;
@end

NS_ASSUME_NONNULL_END

TestClass+addNewMethod.m


#import "TestClass+addNewMethod.h"

@implementation TestClass (addNewMethod)
- (void)printName{
    NSLog(@"printName%s==addNewMethod",__func__);
}
@end

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!