iOS KVO底层原理探索

2020-10-27  本文已影响0人  携YOU手同行

一,KVO (Key-Value Observing)

KVOObjective-C对观察者设计模式的一种实现,它提供一种机制,指定一个被观察对象(如A类),当对象中的某个属性发生变化的时候,对象就会接收到通知,并作出相应的处理。在MVC设计架构下的项目,KVO机制很适合实现mode模型和view视图之间的通讯。例如:代码中,在模型类A创建属性数据,在控制器中创建观察者,一旦属性数据发生改变就收到观察者收到通知,通过KVO再在控制器使用回调方法处理实现视图B的更新;

二,KVO底层实现原理

三,KVO原理验证过程

3.1 环境准备

@interface Person : NSObject
@property (copy, nonatomic) NSString *name;
@end
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // Do any additional setup after loading the view.
    
    self.person = [[Person alloc]init];
    
    [self.person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:NULL];
    
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    self.person.name = [NSString stringWithFormat:@"测试+%@",@"1"];
    
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"改变&&&&change   %@",change);
    
}

-(void)dealloc{
    
    [self.person removeObserver:self forKeyPath:@"name"];
    
}

以上就是相关的环境搭建,相信只要接触iOS开发的同学都知道怎么使用KVO,接下来就让我进一步验证相关原理的实现过程。

3.2 原理验证

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
NSLog(@"改变&&&&change %@",change);
}

打印结果

2020-10-27 22:40:25.093093+0800 TheoryOfKVO[1154:48721] 改变&&&&change {
kind = 1;
new = "\U6d4b\U8bd5+1";
}

我们在以上内容打印的过程中能看到相关的打印内容,kind = 1我们进入代码的定义查看可知

typedef NS_ENUM(NSUInteger, NSKeyValueChange) {
    NSKeyValueChangeSetting = 1,
    NSKeyValueChangeInsertion = 2,
    NSKeyValueChangeRemoval = 3,
    NSKeyValueChangeReplacement = 4,
};

NSKeyValueChangeSetting = 1, 也就是属性的setter方法,NSKeyValueChangeInsertion = 2,是集合类型的添加方法,NSKeyValueChangeRemoval = 3,是集合的移除操作,NSKeyValueChangeReplacement = 4,是可变集合类型的元素替换。

从而就验证了底层会生存一个派生类,继承自Person

这一步其实很好验证的,我们在实现的类中重写+(BOOL)accessInstanceVariablesDirectly 使其返回值为NO,这样如果我们不手动实现以上的两个改变属性值得方法,我们是打印不出任何值得改变的,然而我们手动实现这两个方法时,

-(void)setName:(NSString *)name
{
    [self willChangeValueForKey:name];
    _name = [name copy];
    [self didChangeValueForKey:name];
    
}

+(BOOL)accessInstanceVariablesDirectly
{
    return NO;
}

此时控制台打印的内容和我们监听的一抹一样。这就是通过willChangeValueForKeydidChangevlueForKey改变属性值得过程;

(lldb) po object_getClassName(self.person)
"Person"

以上就是相关的验证过程;

四,总结

以上就是本人通过学习KVO得出的相关结论和验证,至于自定义KVO的实现,其中用到了很多Runtime的API,还不是完全掌握,后续如果自己有更深的立即将会继续补充完整,希望是一个不断学习和提升的过程。有不足之处请多多指教。

上一篇 下一篇

猜你喜欢

热点阅读