实际开发过程中,我们可能需要这样的需求: 想要为一个系统方法或者自定义方法加一些判断条件,但是重写系统方法(或自定义方法)再在每个调用的地方修改再费时费力,而且效果不美好,很容易有遗漏等情况
所以这时候我们就需要用到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函数就不会执行