简单的KVO实现方式

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

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

谢谢~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,855评论 0 9
  • 上半年有段时间做了一个项目,项目中聊天界面用到了音频播放,涉及到进度条,当时做android时候处理的不太好,由于...
    DaZenD阅读 8,114评论 0 26
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,382评论 30 472
  • 概要 本文主要介绍的是 1、 @property 语法在不同场景的语义以及注意事项。 2、Category中实现 ...
    CoderHG阅读 4,717评论 0 3
  • 因为笔者是日本文化爱好者,因此尝尝看一些日本的动漫和轻小说,同时也对日本文学有着稍微了解,而在诸多动漫和轻小说作品...
    飘荡的果壳阅读 4,432评论 0 2