iOS-Runtime方法交换

iOS开发中需要在原有的方法之后执行新的方法,如果我们想在UIController中的viewWillAppear之后执行其他的操作,或者说需要重写原有的设置颜色,位置等操作,都可以通过方法交换实现,实际操作也很简单,通过分类方法中的load方法实现:

@implementation UIViewController (FlyElephant)

+(void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        
        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(fe_viewWillApper:);
        
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        
        BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if (success) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

-(void)fe_viewWillApper:(BOOL)animated{
    NSLog(@"FlyElephant--fe_viewWillApper");
}

@end
FlyElephant.png

方法交换的时候有两点是需要注意的:
1.如果原有的父类中是没有定义的原始方法,那么originalSelector没有对应的执行方法,所以我们需要通过class_method将替换方法实现给originalSelector,看到网上有人没有判断直接进行交换是不正确的实现;
2.如果originalSelector对应的有执行,简单替换即可;

load与initialize 之间的区别,可以参考下篇文章:
http://blog.leichunfeng.com/blog/2015/05/02/objective-c-plus-load-vs-plus-initialize/

你可能感兴趣的:(iOS-Runtime方法交换)