1. 应用
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.tom = [[Person alloc] init];
self.tom.age = 1;
self.jack = [[Person alloc] init];
self.jack.age = 2;
//添加监听
[self.tom addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
//查找setAge方法地址
NSLog(@"tom - %p", [self.tom methodForSelector:@selector(setAge:)]);
NSLog(@"jack - %p", [self.jack methodForSelector:@selector(setAge:)]);
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
NSLog(@"%@-%@-%@",object,keyPath,change);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
self.tom.age ++;
//手动触发监听方法
[self.tom willChangeValueForKey:@"age"];
[self.tom didChangeValueForKey:@"age"];
}
- (void)dealloc {
//移除监听
[self.tom removeObserver:self forKeyPath:@"age"];
}
2. 本质
当未给对象添加监听时,对象的isa指针指向它的类对象
当给对象添加监听时,对象的isa指针指向类对象NSKVONotifying_Person,NSKVONotifying_Person类为Person类的子类,此类为runtime动态生成
NSKVONotifying_Person类中的setAge方法和Person中的setAge方法
3. 获取类对象的方法
- (void)printMethodForClass:(Class)cls{
unsigned int count;
Method* methodList = class_copyMethodList(cls, &count);
for (int i = 0; i < count; i++) {
Method itemMothod = methodList[I];
NSString* methodName = NSStringFromSelector(method_getName(itemMothod));
NSLog(@"%@",methodName);
}
//释放
free(methodList);
}
[self printMethodForClass:object_getClass(self.tom)];