kvo 观察者的本质是,是否有调用set方法
自定义KVO
实现观察People类的name属性
People.h
@interface People : NSObject
@property (nonatomic,copy)NSString *name;
@end
1.实现NSObject分类(类别)
.h文件中
#import
@interface NSObject (KVO)
- (void)ym_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
@end
.m文件中
#import "NSObject+KVO.h"
#import
#import "NSKVONotifying_People.h"
NSString *const observerKey = @"observer";
@implementation NSObject (KVO)
-(void)ym_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
{
// 1.自定义NSKVONotifying_Person子类
// 2.重写setName,在内部恢复父类做法,通知观察者
// 3.如何让外界调用自定义Person类的子类方法,修改当前对象的isa指针,指向NSKVONotifying_Person
objc_setAssociatedObject(self, (__bridge const void *)(observerKey), observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
//修改isa指针
object_setClass(self, [NSKVONotifying_People class]);
}
@end
2.创建NSKVONotifying_People 继承people类
.h文件中
#import "People.h"
@interface NSKVONotifying_People : People
@end
.m文件中
#import "NSKVONotifying_People.h"
#import
extern NSString *const observerKey;
@implementation NSKVONotifying_People
- (void)setName:(NSString *)name
{
//恢复父类的set方法
[super setName:name];
// 通知观察者调用observeValueForKeyPath
// 需要把观察者保存到当前对象
// 获取观察者
id observer = objc_getAssociatedObject(self, (__bridge const void *)(observerKey));
[observer observeValueForKeyPath:@"name" ofObject:self change:nil context:nil];
}
@end
如何使用:
People *p = [[People alloc] init];
//调用自定义KVO
[p ym_addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
实现下面方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"%@",_p.name);
}
到此结束
网友评论