小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
我们知道如果想挽救实例方法和类方法,需要在类中实现resolveInstanceMethod
和resolveClassMethod
方法。如果想对每一个类方法都进行挽救处理,则需要在每一个类中都实现这两个方法。如此繁琐的操作,有没有更好的实现方式呢?
对于实例方法的查找流程,通过类对象、父类、最后找到根类。而类方法的查找流程,通过元类、根元类、最后同样找到根类。
在根类中,无论是实例方法还是类方法,找不到时都会调用resolveInstanceMethod
。所以我们只需要在NSObject
中,实现resolveInstanceMethod
方法,就可以对所有类的实例方法及类方法都进行挽救处理。
创建NSObject+LG
分类,写入以下代码:
#import "NSObject+LG.h"
#import <objc/runtime.h>
@implementation NSObject (LG)
-(void)say666{
NSLog(@"666");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel{
if(sel==@selector(sayNB)){
NSLog(@"resolveInstanceMethod:%@,%@", self, NSStringFromSelector(sel));
IMP imp = class_getMethodImplementation(self, @selector(say666));
Method methodSay666 = class_getInstanceMethod(self, @selector(say666));
const char *type = method_getTypeEncoding(methodSay666);
return class_addMethod(self, @selector(sayNB), imp, type);
}
return NO;
}
@end
在main函数中,调用LGPerson
的sayNB
类方法,同时调用实例对象per的sayNB
方法
int main(int argc, const char * argv[]) {
@autoreleasepool {
[LGPerson sayNB];
LGPerson *per= [LGPerson alloc];
[per sayNB];
}
return 0;
}
-------------------------
//输出结果:
实例方法-say666
实例方法-say666
此方案的优点:
- 任意一个类,只要继承自
NSObject
,它的所有方法都可以被监听到 - 我们可以将自定义方法按指定策略进行命名,然后按照相同策略进行监听,只要遇到符合策略的方法无法找到时,可以将其上报服务端,让开发者在第一时间得到问题的反馈
- 在
NSObject
分类中对所有方法统一监听,这种方式符合AOP面向切面的设计模式- 传统
OOP
面向对象设计模式,虽然每一个对象的分工都非常明确,但他们之间一些相同行为,会导致大量的冗余代码。如果我们将其提取,创建公共类进行继承,势必造成强依赖与高耦合 - 而
AOP
的优势,对于原始的类与对象无侵入,只要维护好NSObject
分类中的监听方法即可 缺点:
- 传统
- 在监听方法中写入大量判断条件,不利于查找与维护
- 所有的方法都被监听,其中呢包含了大量的系统方法,造成性能消耗
- 在
NSObject
分类中监听,导致系统提供的消息转发流程无法触发 对于容错处理,我们应该给开发者更大的容错空间。所以我们使用AOP
设计模式,提供的“优化”方案,在这个场景下并不是一个真正的好方案。