kvo实现原理_KVO - 原理解析和应用

KVO是一种观察者模式,需要观察者&被观察者的对象属性,移除观察者1.使用(参数的意义,哪些地方使用了KVO)

2. 开启方式:手动和自动

3. 原理解析:系统做了哪些东西;是否监听地址变化?

4. 容器类监听使用

5. 多级路径属性管理

6. KVO为什么是基于KVC的:KVC是KVO的一个入口而已

使用场景(哪些地方使用了KVO)1.NSOperation

2.NSoperationQueue

3.RAC

开启方式:手动&自动1.自动:只需要实现响应的

2.手动触发:

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key

{

return NO;

}上面的代码返回NO之后,你还需要自己手动触发KVO:此时willchange & didchange 缺一不可

Person *p = [Person new];

[p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];

[p willChangeValueForKey:@"name"];

p.name = @"new_name";

[p didChangeValueForKey:@"name"];手动触发KVO:可以自己控制在某些条件下进行KVO

原理解析:利用Runtime,生成一个类的子类,并生成子类对象,并替换了原来对象的isa指针,并且重写了set方法

1. KVO的本质是set方法,只有调用了set方法才会触发KVO我们写一个Person类,设置age & name两个属性:

#import

NS_ASSUME_NONNULL_BEGIN

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;

@property (nonatomic, assign) int age;

@end

NS_ASSUME_NONNULL_END正常的Person对象的布局

当我们添加addObserver之后,runtime会对Person对象重新布局:重新布局后

从上面的关系图,我们可以看到runtime为我们生产NSKVONotifying_Person类,继承自Person;并修改了Person实例对象的isa指针,指向新的类。而且重写set方法:

- (void)setName:(NSString *)name

{

[self willChangeValueForKey:@"name"];

_name = name;

[self didChangeValueForKey:@"name"];

}

容器类的KVO --NSArray, NSDictionary

初始化一个容器属性:

@interface Person : NSObject

@property (nonatomic, copy) NSString *name;

@property (nonatomic, assign) int age;

@property (nonatomic, strong) NSArray *ecoArr;

@end[p.ecoArr addObject:@"LI"];这样调用可以出发KVO吗?

A: 不会,因为这样没有调用属性ecoArr的set方法。

[[p.ecoArr mutableArrayValueForKeyPath:@"eocArr"] addObject:@"li"];这样就就可以对这个容器进行插入KVO观察。

typedef NS_ENUM(NSUInteger, NSKeyValueChange) {

NSKeyValueChangeSetting = 1,

NSKeyValueChangeInsertion = 2,

NSKeyValueChangeRemoval = 3,

NSKeyValueChangeReplacement = 4,

};

对于容器类的KVO我们还可以监听容器属性是发生的插入、移除、替换操作。

多级路径属性管理

+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key

{

NSSet *keySet = [super keyPathsForValuesAffectingValueForKey:key];

NSSet *a = [NSSet setWithObject:@"_person.age"];

keySet = [keySet setByAddingObjectsFromSet:a];

return keySet;

}

这样可以将多及路径进行观测,这里注意object写法是要下划线_person

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值