响应式编程
假设有一个父类Person,它有个属性age,我们创建一个它的子类 LYKVONotifying_Person。
我们给所有类一个扩展方法:
1
- (void)ly_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
实现这个方法:
实质是修改这个对象的isa指针,把当前对象指向一个新的类,然后给对象绑定观察者对象。
1
2
3
4
5
6
7
- (void)ly_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context{
//修改isa指针,就是把当前对象指向一个新的类
object_setClass(self, [LYKVONotifying_Person class]);
//给对象绑定观察者对象
objc_setAssociatedObject(self, @"observer", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
最后重写这个子类的 setAge 方法:
每次调用setAge方法,都会调用观察者的observeValueForKeyPath方法
1
2
3
4
5
6
7
8
9
10
- (void)setAge:(int)age{
[super setAge:age];
//KVO
//获取观察者
id observer = objc_getAssociatedObject(self, @"observer");
//调用观察者方法
[observer observeValueForKeyPath:@"age" ofObject:observer change:nil context:nil];
}
检验:
1
2
3
4
5
6
7
8
9
10
11
12
- (void)viewDidLoad {
[super viewDidLoad];
//创建一个父类的对象
Person *p = [[Person alloc] init];
p.age = 0;
_person = p;
//调用新的注册观察者方法
[p ly_addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
}
响应:
1
2
3
4
5
6
//响应方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
NSLog(@"Person Age %d Changed",_person.age);
}
点击按钮,设置person的age属性:
1
2
3
4
5
6
7
8
- (IBAction)changeAge:(id)sender {
//0~99随机数
int newAge = arc4random_uniform(100);
NSLog(@"New Age -> %d",newAge);
//调用setAge方法
_person.age = newAge;
}
打印结果: