Person *p1 = [[Person alloc] init];
Person *p2 = [[Person alloc] init];
// 监听前后对象的类对象有没有变化
id class1 = object_getClass(p1);
id class2 = object_getClass(p2);
IMP imp1 = [p1 methodForSelector:@selector(setName:)];
IMP imp2 = [p2 methodForSelector:@selector(setName:)];
id superClass1 = class_getSuperclass(class1);
id superClass2 = class_getSuperclass(class2);
NSLog(@"KVO监听前:p1:%@ p2:%@", p1, p2);
NSLog(@"KVO监听前:p1.class:%@ p2.class:%@",class1, class2);
NSLog(@"KVO监听前:imp1:%p imp2:%p",imp1, imp2);
NSLog(@"KVO监听前:superclass1:%@ superclass2:%@",superClass1, superClass2);
[p1 addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
class1 = object_getClass(p1);
class2 = object_getClass(p2);
imp1 = [p1 methodForSelector:@selector(setName:)];
imp2 = [p2 methodForSelector:@selector(setName:)];
superClass1 = class_getSuperclass(class1);
superClass2 = class_getSuperclass(class2);
NSLog(@"KVO监听后:p1:%@ p2:%@",p1, p2);
NSLog(@"KVO监听后:p1.class:%@ p2.class:%@",class1, class2);
NSLog(@"KVO监听后:imp1:%p imp2:%p",imp1, imp2);
NSLog(@"KVO监听后:superclass1:%@ superclass2:%@",superClass1, superClass2);
NSString *methodList1 = [self printPersonMethods:class1];
NSString *methodList2 = [self printPersonMethods:class2];
NSLog(@"KVO监听后:methodlist1:%@ \n methodlist2:%@",methodList1, methodList2);
// 没有任何变化
KVO监听前:p1:<Person: 0x6000036287f0> p2:<Person: 0x6000036287d0>
KVO监听后:p1:<Person: 0x6000036287f0> p2:<Person: 0x6000036287d0>
// p1.class: NSKVONotifying_Person p2.class: Person
// p1的类对象发生改变
KVO监听前:p1.class:Person p2.class:Person
KVO监听后:p1.class:NSKVONotifying_Person p2.class:Person
// p1的setName:方法实现IMP指针发生变化
KVO监听前:imp1:0x104e50db0 imp2:0x104e50db0
KVO监听后:imp1:0x10512198b imp2:0x104e50db0
// superclass1:Person superclass2:NSObject
// 所以NSKVONotifying_Person是一个 Person 子类(苹果Runtime动态创建Person的一个子类)
KVO监听前:superclass1:NSObject superclass2:NSObject
KVO监听后:superclass1:Person superclass2:NSObject
methodlist1:[
setName:
class
dealloc
_isKVOA
]
methodlist2:[
.cxx_destruct
name
setName:
]
// 打印结果可以看出都有 setName:方法
// 但是 methodList1里面重写了setName: class 和 dealloc 方法,而且还多了一个_isKVOA方法
// 重写setName: 是为了在该方法里面调用_NSSetObjectValueAndNotify()方法
// 重写class方法是为了返回Person类
// 重写dealloc方法是为了向外界隐藏NSKVONotifying_Person子类的存在
// 所以这就是我们开始直接打印p1和p2都是Person类的原因
- (NSString *) printPersonMethods:(id)obj {
unsigned int count = 0;
Method *methods = class_copyMethodList([obj class],&count);
NSMutableString *methodList = [NSMutableString string];
[methodList appendString:@"[\n"];
for (int i = 0; i<count; i++) {
Method method = methods[i];
SEL sel = method_getName(method);
[methodList appendFormat:@"%@",NSStringFromSelector(sel)];
[methodList appendString:@"\n"];
}
[methodList appendFormat:@"]"];
free(methods);
return methodList;
}
网友评论