#import "ViewController.h"
#import <objc/runtime.h>
///打印某个类的所有成员方法
void getAllMethodsOfClass(Class cls) {
unsigned int count;
Method *methods = class_copyMethodList(cls, &count);
NSMutableArray *array = [NSMutableArray array];
for (unsigned int i = 0; i < count; i++) {
Method method = methods[i];
[array addObject:NSStringFromSelector(method_getName(method))];
}
NSString *methodName = [array componentsJoinedByString:@", "];
NSLog(@"\n方法名: \n%@", methodName);
}
@interface MZPerson : NSObject
@property (nonatomic, assign) NSInteger age;
@end
@implementation MZPerson
- (void)setAge:(NSInteger)age {
_age = age;
}
- (void)willChangeValueForKey:(NSString *)key {
[super willChangeValueForKey:key];
NSLog(@"willChangeValueForKey:");
}
- (void)didChangeValueForKey:(NSString *)key {
NSLog(@"didChangeValueForKey: --start");
[super didChangeValueForKey:key];
NSLog(@"didChangeValueForKey: --end");
}
@end
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
MZPerson *person1 = [[MZPerson alloc] init];
person1.age = 18;
MZPerson *person2 = [[MZPerson alloc] init];
//监听属性值的改变
[person2 addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
//改变值
person2.age = 18;
Class unobservedCls = object_getClass(person1);
Class observedCls = object_getClass(person2);
NSLog(@"\n没有监听类:%@\n监听之后的%@", unobservedCls, observedCls);
NSLog(@"被监听类的父类是: %@", observedCls.superclass);
//打印所有的成员方法
getAllMethodsOfClass(observedCls);
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
NSLog(@"%@---%@", change[NSKeyValueChangeOldKey], change[NSKeyValueChangeNewKey]);
}
@end
输出:
willChangeValueForKey:
didChangeValueForKey: --start
0---18
didChangeValueForKey: --end
没有监听类:MZPerson
监听之后的NSKVONotifying_MZPerson
被监听类的父类是: MZPerson
方法名:
setAge:, class, dealloc, _isKVOA

从打印可以看出:
- 1、被监听的属性所属的类会由runtime动态生成一个类
NSKVONotifying_MZPerson
,该类继承自MZPerson,并将被监听属性的 isa 指针指向新生成的类; - 2、新生成的类里有四个方法,分别是setAge:, class, dealloc, _isKVOA,其中前三个为重写的方法;
- 3、被监听属性的值发生改变,是通过
_NSSetLongLongValueAndNotify()
处理并且通知调用- observeValueForKeyPath:ofObject:change:context:
。
网友评论