runtime 交换实例方法和对象方法标准写法

2017-02-07  本文已影响58人  kelvin943

交换实例方法:其中Class参数一定得是实例对象的类(实例对象的isa指向它的Class(储存所有减号方法)object_getClass(obj))

static void _exchanged_instance_method(SEL originalSelector, SEL swizzledSelector, Class class){
    Method originalMethod = class_getInstanceMethod(class, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
    BOOL didAddMethod =
    class_addMethod(class,
                    originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        class_replaceMethod(class,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    }
    else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

交换静态方法(类): 其中class 参数一定要元类(metaClass),Class对象的isa指向元类(储存所有加号方法)object_getClass(object_getClass(obj))

static void _exchanged_class_method(SEL originalSelector, SEL swizzledSelector, Class class){
    Method originalMethod = class_getClassMethod(class, originalSelector);
    Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
    BOOL didAddMethod =
    class_addMethod(class,
                    originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        class_replaceMethod(class,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    }
    else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

注意: 静态方法中的self 是类对象,实例方法中的self 是实例对象,可以用一下方法测试一下:

- (void)viewDidLoad {
    [super viewDidLoad];

    [self  instanceMethod];
    [ViewController classMethod];
}

- (void)instanceMethod {
    NSLog(@"%p",self);
    NSLog(@"%p",object_getClass((id)self));
}

+ (void)classMethod1 {
    NSLog(@"%p",self);
   //[self instanceMethod]       会报错找不到instanceMethod 方法
   //[self classMethod2]         编译器不会报错而且能正常调用
}
+ (void)classMethod2{
    NSLog(@"%p",self);

}

最后附一幅经典的图:

上一篇 下一篇

猜你喜欢

热点阅读