步骤:
1.生成一个Person类的子类 NSKVONotifying_Person
2.使当前对象的isa指向新的类,就会调用新类的set方法
3.重写NSKVONotifying_Person的setAge方法,每次调用,就调用观察者的observeValueForKeyPath方法
4.如何在set方法中,拿到观察者,使用运行时让当前对象关联观察者这个属性。
#import "ViewController.h"
#import "Person.h"
#import "NSObject+KVO.h"
@interface ViewController ()
@property (nonatomic, strong) Person *person;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Person *p = [[Person alloc] init];
p.age = 0;
_person = p;
[p wb_addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
NSLog(@"person的值改变了:%d",_person.age);
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
_person.age = 10;
}
@end
#import "WBKVONotifying_Person.h"
#import <objc/runtime.h>
@implementation WBKVONotifying_Person
- (void)setAge:(int)age
{
[super setAge:age];
// 调用KVO
// 获取观察者
id observer = objc_getAssociatedObject(self, @"observer");
// 调用观察者的方法
[observer observeValueForKeyPath:@"age" ofObject:observer change:nil context:nil];
}
@end
#import <Foundation/Foundation.h>
@interface NSObject (KVO)
- (void)wb_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
@end
#import "NSObject+KVO.h"
#import <objc/runtime.h>
#import "WBKVONotifying_Person.h"
@implementation NSObject (KVO)
- (void)wb_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
{
// 修改isa指针,就是把当前对象指向一个新类
object_setClass(self, [WBKVONotifying_Person class]);
// 给对象绑定观测者对象
objc_setAssociatedObject(self, @"observer", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end