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。实验时这样的:
用法, 比系统的KVO还要简单。
但是,一定要主要指针循环:
其它
正常情况下,监听之后是这个样子的:
但是,如果做了如下处理的话。
结果就是这个样子的:
意思是没有改变isa指针。
在这种情况下就不会有KVO效果了。但是, 可以这么弄:
这样就可以了, 突然脑补了一下, 把这条代码注释了, 可否:
答案、肯定是不可以的,不信你把代码代码代码下载下来试试。