kvo实现原理
自动创建一个原来类的子类,如NSKVONotifying_XX,将原来类的isa指针指向新建的类,重写setter方法,通过willChangeValueForKey,didChangeValueForKey
来检测属性值的变化。
removeObserver
就是将isa指针指向原来的类
举个栗子:
//XYPerson.h
#import <Foundation/Foundation.h>
@interface XYPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSUInteger age;
- (void)printInfo;
@end
//XYPerson.m
#import "XYPerson.h"
#import <objc/runtime.h>
@implementation XYPerson
- (void)printInfo{
NSLog(@"isa:%@, supper class:%@", NSStringFromClass(object_getClass(self)), class_getSuperclass(object_getClass(self)));
NSLog(@"self:%@, [self superclass]:%@", self, [self superclass]);
NSLog(@"age setter function pointer:%p", class_getMethodImplementation(object_getClass(self), @selector(setAge:)));
NSLog(@"name setter function pointer:%p", class_getMethodImplementation(object_getClass(self), @selector(setName:)));
NSLog(@"printInfo function pointer:%p", class_getMethodImplementation(object_getClass(self), @selector(printInfo)));
}
@end
//MainController.m
- (void)viewDidLoad {
[super viewDidLoad];
XYPerson *person = [XYPerson new];
person.name = @"Will";
person.age = 30;
self.person = person;
[self.person printInfo];
[self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
NSLog(@"------------");
[self.person printInfo];
[self.person removeObserver:self forKeyPath:@"name"];
NSLog(@"------------");
[self.person printInfo];
}
打印如下
2018-03-06 15:22:46.631080+0800 tableView[50139:1031782] isa:XYPerson, supper class:NSObject
2018-03-06 15:22:46.631372+0800 tableView[50139:1031782] self:<XYPerson: 0x60400003c440>, [self superclass]:NSObject
2018-03-06 15:22:46.631485+0800 tableView[50139:1031782] age setter function pointer:0x101e876a0
2018-03-06 15:22:46.631692+0800 tableView[50139:1031782] name setter function pointer:0x101e87640
2018-03-06 15:22:46.631800+0800 tableView[50139:1031782] printInfo function pointer:0x101e873a0
2018-03-06 15:22:46.632256+0800 tableView[50139:1031782] ------------
2018-03-06 15:22:46.632437+0800 tableView[50139:1031782] isa:NSKVONotifying_XYPerson, supper class:XYPerson
2018-03-06 15:22:46.632654+0800 tableView[50139:1031782] self:<XYPerson: 0x60400003c440>, [self superclass]:NSObject
2018-03-06 15:22:46.632782+0800 tableView[50139:1031782] age setter function pointer:0x101e876a0
2018-03-06 15:22:46.632888+0800 tableView[50139:1031782] name setter function pointer:0x104ab6efe
2018-03-06 15:22:46.632979+0800 tableView[50139:1031782] printInfo function pointer:0x101e873a0
2018-03-06 15:22:46.633102+0800 tableView[50139:1031782] ------------
2018-03-06 15:22:46.634074+0800 tableView[50139:1031782] isa:XYPerson, supper class:NSObject
2018-03-06 15:22:46.634357+0800 tableView[50139:1031782] self:<XYPerson: 0x60400003c440>, [self superclass]:NSObject
2018-03-06 15:22:46.634536+0800 tableView[50139:1031782] age setter function pointer:0x101e876a0
2018-03-06 15:22:46.634644+0800 tableView[50139:1031782] name setter function pointer:0x101e87640
2018-03-06 15:22:46.634779+0800 tableView[50139:1031782] printInfo function pointer:0x101e873a0
addObserver新建了一个继承于XYPerson
的NSKVONotifying_XYPerson
类