简单的KVO实现方式

2018-02-27 11:13:10来源:https://www.jianshu.com/p/d09492257829作者:CoderHG人点击

分享


KVO是什么?

简单地说、就是一个监听,同时也是一种设计模式。监听??那什么时候会被触发呢?具体的大家可以参考我的上一篇介绍:KVO与Category,主要介绍了KVO的简单使用以及在Category中动态添加成员变量实现KVO监听。其中也介绍了,被注册监听的字段被触发KVO的条件是必须调用setter方法。


KVO实现

创建一个干净的Class,名叫SimpleObject。
.h文件是这样的:



#import <Foundation/Foundation.h>
// KVO 回调
typedef void(^KVOBlock)(id oldValue, id newValue);
@interface SimpleObject : NSObject
/** 属性 */
@property (nonatomic, copy) NSString* hgName;
/**
史上最简单的KVO监听方法
@param keyPath keyPath
@param kvoBlock 回调
*/
- (void)addKVOforKeyPath:(NSString*)keyPath kvoBlock:(KVOBlock)kvoBlock;
@end

一个辅助Class:



@interface Path8KVOBlockObject : NSObject
/** 被监听的 keyPath */
@property (nonatomic, copy) NSString* keyPath;
/** 被监听的 回调 */
@property (nonatomic, copy) KVOBlock kvoBlock;
@end
@implementation Path8KVOBlockObject
@end

先来看看的监听方法的实现:


/**
史上最简单的KVO监听方法
@param keyPath keyPath
@param kvoBlock 回调
*/
- (void)addKVOforKeyPath:(NSString*)keyPath kvoBlock:(KVOBlock)kvoBlock {
if (!keyPath || !kvoBlock) {
return;
}
// 初始化 _keyPath8KVOBlockArrM
if (!_keyPath8KVOBlockArrM) {
_keyPath8KVOBlockArrM = [NSMutableArray array];
}

// 获取
Path8KVOBlockObject* pbObject = [self pbObjectForKeyPath:keyPath];
if (!pbObject) {
// 没有就重新创建
pbObject = [[Path8KVOBlockObject alloc] init];
[_keyPath8KVOBlockArrM addObject:pbObject];
}
// 赋值
pbObject.keyPath = keyPath;
pbObject.kvoBlock = kvoBlock;

}

这个方法的功能类似与系统的这个方法:addObserver: forKeyPath: options: context:。


重写被监听的setter方法:



- (void)setHgName:(NSString *)hgName {
// 保留旧值
NSString* oldValue = _hgName;
// 赋值
_hgName = hgName.copy;

// 找到对应的监听, 然后执行
Path8KVOBlockObject* pbObject = [self pbObjectForKeyPath:@"hgName"];
if (pbObject.kvoBlock) {
pbObject.kvoBlock(oldValue, _hgName);
}
}

这样,一个最简单的KVO实现就是OK了, 没有运行时,也没有Runloop。实验时这样的:





image.png

用法, 比系统的KVO还要简单。


但是,一定要主要指针循环:





image.png
其它

正常情况下,监听之后是这个样子的:





image.png

但是,如果做了如下处理的话。





image.png

结果就是这个样子的:





image.png

意思是没有改变isa指针。


在这种情况下就不会有KVO效果了。但是, 可以这么弄:





image.png

这样就可以了, 突然脑补了一下, 把这条代码注释了, 可否:





image.png

答案、肯定是不可以的,不信你把代码代码代码下载下来试试。


谢谢~






最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台