runtime使用二:使用runtime实现方法交换(Method Swizzling)

实际开发过程中,我们可能需要这样的需求: 想要为一个系统方法或者自定义方法加一些判断条件,但是重写系统方法(或自定义方法)再在每个调用的地方修改再费时费力,而且效果不美好,很容易有遗漏等情况
所以这时候我们就需要用到runtime的方法交换,照常调用系统方法或自定义方法,但是运行时实际走的是我们交换了之后的那个方法
现在我们来看他的实现
调用处:

#import "ViewController.h"
#import "NSMutableDictionary+runtime.h"

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
   
    NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
    NSString *key = nil;
    [dic setObject:@"test" forKey:key];
}

在没有做任何处理的情况下,我们为一个字典设置一个key为空的值,是会崩溃的,但是这里我们做了个方法交换,在调用setObject: forKey: 之前对key值做了判断,以下是方法交换代码


#import "NSMutableDictionary+runtime.h"
#import <objc/runtime.h>

@implementation NSMutableDictionary (runtime)

+ (void)load {

    Method method1 = class_getInstanceMethod(objc_getClass("__NSDictionaryM"), @selector(setObject:forKey:));
    Method method2 =  class_getInstanceMethod(objc_getClass("__NSDictionaryM"), @selector(zsh_setObject:forKey:));
    method_exchangeImplementations(method1, method2);
}

- (void)zsh_setObject:(id)anObject forKey:(id<NSCopying>)aKey {
    
    if (aKey != nil) {
        
        [self zsh_setObject:anObject forKey:aKey];
    } else {
        
        NSLog(@"zhousuhua --- akey不可以为空");
    }
}
@end

运行结果:

zhousuhua --- akey不可以为空

这里的load方法会比main函数还要先调用,由于我们的程序是预加载的,要想load不调用,可以在这里把他删掉在这里插入图片描述
这样load函数就不会执行

发布了40 篇原创文章 · 获赞 10 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/ai_pple/article/details/90175532