文档章节

iOS-KVO

麦兜卖鱼丸
 麦兜卖鱼丸
发布于 2017/07/05 09:59
字数 787
阅读 21
收藏 0
KVO

前言

KVO键值观察,我们再熟悉不过了。但是大部分人对它的关注点可能都在对观察某一个keyPath,会动态创建一个继承该类的带前缀NSKVONotifying_原类名的子类,并且在子类中重写该key的setter方法这一逻辑。今天我们来看一些可能平时不太注意的地方,并且讨论一下KVO键值观察为什么要创建子类来实现。

 

触发通知方式;

(1)自动通知,这种应该是比较常见的,原因在于NSObject类实现了NSKeyValueCoding协议,因此只要是继承了NSObject类的对象通过KVC进行操作就可以自动的通知到观察者。

(2)手动通知,这就需要让你的类重写+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key或者是+ (BOOL)automaticallyNotifiesObserversOf<key>方法,对于想要手动触发通知的,可以根据keyPath返回NO,而其对于其他位置的keyPath,要返回父类的这个方法。例如属性observingStr;

+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
{
    if ([key isEqualToString:@"observingStr"]) {
        return NO;
    }
    return YES;
}

+ (BOOL)automaticallyNotifiesObserversOfObservingStr
{
    return NO;
}

 

手动触发;

(1)要实现手动通知,你需要在值改变前调用 willChangeValueForKey: 方法,在值改变后调用 didChangeValueForKey: 方法。你可以在发送通知前检查值是否改变,如果没有改变就不发送通知。关键在于willChangeValueForKey:以及didChangeValueForKey:这两个方法,自动通知应该就是在子类重写的setter中封装好触发通知的逻辑。

(2)其实手动触发通知有一个细节的地方,不知道有没有人注意到,就是当你设置某个键值需要手动通知时,系统并没有去动态创建带前缀NSKVONotifying_原类名,你可以通过rumtime的object_getClass(self),去验证self的isa是否指向新类,答案是没有。

 

KVO键值观察为什么要创建子类来实现?

(1)上文也说了触发键值观察的关键方法willChangeValueForKey:和didChangeValueForKey:,我们做个假设,假设苹果KVO机制并没有通过创建子类实现,而是在当前类实现。那么会存在一个问题,就是开发者重写该属性的setter方法,并且并没有去执行willChangeValueForKey:和didChangeValueForKey:两个方法,就不会触发通知观察者。

(2)有可能跟类设计的单一责任原则有关,子类自负责封装触发通知逻辑,其他的一概不管(例如获取旧值以及赋值新值都会执行父类的方法)。例如;

- (void)setObservingStr:(NSString *)observingStr
{
    [self willChangeValueForKey:@"observingStr"];
    NSLog(@"%@", NSStringFromClass(object_getClass(self)));
    //_observingStr = observingStr;
    //[self didChangeValueForKey:@"observingStr"];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"observingStr"]) {
        NSLog(@"newStr -- %@", change[NSKeyValueChangeNewKey]);
        
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

由于重写的setter方法没有赋值新值,输出newStr -- <null>;这也说明子类重写的setter方法取值和赋值是通过父类的setter方法。

 

总结

本文所讲的内容只是KVO的一部分,用于记录平时研究一些技术的心得,了解更多的内容可以查看这篇文章或者是上网查询更多内容。

© 著作权归作者所有

共有 人打赏支持
麦兜卖鱼丸
粉丝 12
博文 69
码字总数 69333
作品 0
桂林
iOS工程师
如何对NSMutableArray进行KVO

本文是我首发在iOS知识小集团队的,欢迎关注微博话题#ios知识小集#。我的微博:halohily 我们知道,iOS 中 KVO (key-value-observing) 的原理,简单来说就是重写了被观察属性的 set 方法。自...

halohily
05/22
0
0
iOS高仿QQ侧滑控件、下载框架、动画效果、扫一扫、颜色变化、K线图等源码

iOS精选源码 仿京东"加入购物车"转场动画(http://www.code4app.com/thread-28162-1-1.html) ColorTool(颜色转换)(http://www.code4app.com/thread-29256-1-1.html) Swift 专业版K线(http://w......

sunnyaigd
04/17
0
0
iOS源码补完计划--AFNetworking(二)

目录 前言 AFNetworkReachabilityManager.h AFNetworkReachabilityManager.m API注释Demo 参考资料 前言 AFNetworking源码第二篇 主要看了看AFNetworkReachabilityManager的内容 作为一个辅助...

kirito_song
05/16
0
0
Knowledge-Reserve

Knowledge-Reserve ComputerOperatingSystem 编译 静态库&动态库(Linux) 静态链接&动态链接 内存 内联函数&宏 Static&Const 死锁 线程安全 线程同步 锁 DataStructure Programme 集约型&离散...

旭宝爱吃鱼
08/16
0
0
iOS商城demo、音乐播放器、视频通话、自定义搜索、转场动画等源码

iOS精选源码 微信自定义搜索框实现(http://www.code4app.com/thread-13182-1-1.html) 一个商城Demo,持续更新中(http://www.code4app.com/thread-13957-1-1.html) 在Object-C中学习数据结构与...

sunnyaigd
07/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

计算卷积神经网络浮点数运算量

前言 本文主要是介绍了,给定一个卷积神经网络的配置之后,如何大概估算它的浮点数运算量。 相关代码:CalFlops,基于MXNet框架的 Scala 接口实现的一个计算MXNet网络模型运算量的demo。 正文...

Ldpe2G
今天
1
0
Sql语言与MySql数据库

1. 数据库简介 1. 数据库,就是存储数据的仓库,只能通过sql语言来访问,数据库也是一个文件系统。通常,MySQL、Oracle等数据库,也被称为关系型数据库,其保存的不仅仅只是数据,还包括数据...

江左煤郎
今天
1
0
IDEA 取消自动import .*

打开设置 > Editor > Code Style > Java > Scheme Default > Imports ① 将 Class count to use import with "*" 改为 99 (导入同一个包的类超过这个数值自动变为 * ) ② 将 Names count ......

乔老哥
今天
3
0
PostGIS学习笔记(开篇)

PostGIS事实上算是笔者开始写博客的第一篇内容。而事实上那篇博文的内容并不丰富,笔者对PostGIS的了解仍然不多,然而17年在OSGeo课程学习时对PostGIS又有了进一步了解,并逐步发现它的强大。...

胖胖雕
今天
3
0
【Centos】在nginx服务器中配置php和mysql

接上一章《【Centos】利用Vultr服务器和namesilo布网》(https://my.oschina.net/u/3776619/blog/2051986),在Centos中配置好nginx,并在iptables中开启了80端口,和为了远程mysql操作方便开...

yongh701
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部