@interface NSPerson : NSObject
@property(nonatomic,assign)int age;
@property(nonatomic,assign)double height;
@end
@implentation NSPerson
- (void)setAge:(int)age
{
_age = age;
}
@end
@interface ViewController ()
@property(nonatomic,strong)NSPerson *person;
@end
@ implentation viewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.person = [NSPerson new];
self.person.age = 10;
self.person.height = 180;
}
@end
本质
- runtime动态生成子类
NSKVONotifying_NSPerson
- 修改了setAge:方法
IMP imp = [self.person methodForSelector:@selector(setAge:)];
IMP imp2 = [person2 methodForSelector:@selector(setAge:)];
Printing description of imp:
(IMP) imp = 0x00007fff258f10eb (Foundation`_NSSetIntValueAndNotify)
Printing description of imp2:
(IMP) imp2 = 0x00000001059716e0 (KVO`-[NSPerson setAge:] at NSPerson.h:15)
(lldb)
//伪代码
@implentation NSKVONotifying_NSPerson
- (void)setAge:(int)age
{
_NSSetIntValueAndNotify();
}
void _NSSetIntValueAndNotify()
{
[obj willChangeValueForKey:@"age"];
[super setAge:age];
[obj didChangeValueForKey:@"age"];
}
- (void) didChangeValueForKey:(NSString *)key
{
[observer observeValueForKeyPath:@"age" ofObject:obj
change:@{old, new } context:nil];
}
@end
子类
- (void)printMethodListForClass:(Class)cls
{
unsigned int count;
Method *methodList = class_copyMethodList(cls, &count);
NSMutableString *methodString = [NSMutableString string];
for (int i = 0; i < count; i++) {
Method method = *(methodList + i);
NSString *methodName = NSStringFromSelector(method_getName(method));
[methodString appendFormat:@"%@,",methodName];
}
free(methodList);
NSLog(@"%@",methodString);
}
- (void)viewDidLoad {
[super viewDidLoad];
self.person = [NSPerson new];
self.person.age = 10;
self.person.height = 180;
NSPerson *person2 = [NSPerson new];
person2.age = 20;
person2.height = 175;
NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
[self.person addObserver:self forKeyPath:@"age" options:options context:nil];
[self.person addObserver:self forKeyPath:@"height" options:options context:nil];
[self printMethodListForClass:object_getClass(self.person)];
[self printMethodListForClass:object_getClass(person2)];
}
log
KVO[71463:2802731] setHeight:,setAge:,class,dealloc,_isKVOA,
KVO[71463:2802731] height,setHeight:,age,setAge:,
NSKVONotifying_NSPerson生成了下面方法
- setAge:
- class
- (Class)class
{
return [NSPerson class];
}
- dealloc
- _isKVOA
- (BOOL) _isKVOA
{
return YES;
}
手动触发
[self.person willChangeValueForKey:@"age"];
[self.person didChangeValueForKey:@"age"];
网友评论