iOS

iOS 两种方法交换的区别

2021-01-18  本文已影响0人  哦呵呵y

下面两种实现是在iOS开发中最常用的方法交换方式,那么两种实现方式具体有什么区别呢?
首先,以上两种实现都可以达到方法交换的效果,但是方案二在某些情况下会发生崩溃,而方案一相对安全一些。

方案一:
+ (void)swizzleInstanceMethod:(SEL)originalSel with:(SEL)swizzledSel {

    Method originalMethod = class_getInstanceMethod(self, originalSel);
    Method swizzledMethod = class_getInstanceMethod(self, swizzledSel);
    
    BOOL didAddMethod =
    class_addMethod(self,
                    originalSel,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));
    
    if (didAddMethod) {
        class_replaceMethod(self,
                            swizzledSel,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}
方案二:
+ (void)swizzleInstanceMethod:(SEL)originalSel with:(SEL)swizzledSel {

    Method originalMethod = class_getInstanceMethod(self, originalSel);
    Method swizzledMethod = class_getInstanceMethod(self, swizzledSel);

    method_exchangeImplementations(originalMethod, swizzledMethod);

}
  1. 假设有两个A、B两个类,B是A的子类,
@interface A : NSObject

@end

@implementation A

- (void)test {
    NSLog(@"test");
}

@end

@interface B : A

@end

@implementation B

- (void)btest {
    [self btest];
    NSLog(@"btest");
}

@end
  1. 然后交换B类的方法
    [self swizzleInstanceMethod:@selector(test) with:@selector(btest)];

此时A类的实例调用test方法,就会发生崩溃。
因为 btest方法是属于B类的,那么当[self btest]代码执行时,会发生unrecognized selector错误
由于B类未实现test方法,所以其实交换的是父类的方法,才导致了崩溃。
而第二种方案,首先会为B类添加test方法,如果添加失败,说明B类已经实现了此方法,那么直接交换是没有问题的,如果添加成功说明,B类并没有实现test方法,那么此时只需要替换目标方法的实现就可以了。

上一篇 下一篇

猜你喜欢

热点阅读