ios 中 KVO

KVO(Key value observe)键值观察,是ios中的一种核心的概念,简单的理解为当某一个对象A(或者多个对象)要想监听对象的B的一个或者多个属性发生变化时,就是用这种机制。

  1.  KVO的优点 

        当某个对象有个属性改变,KVO会自动的消息通知对方,这样的架构有多种好处。首先开发人员不需要自己去实现这样的方案:每次属性改变了就发送消息通知,这是KVO机制的最大优点,因为这个方案已经被明确定义,获得框架级的支持,可以方便的采用,开发人员不需要添加任何代码,不需要设计自己的开发者模型,直接就可以在工程里使用,其次KVO的架构非常强大,可以很容易的支持多个观察者观察同一个属性,以及相关的值           

     2、缺点,实时监听对象属性值的改变,非常消耗系统的性能。

     KVO 的面试题。

    1、NSNotification和KVO的区别和用法是什么?什么时候应该使用通知,什么时候应该使用KVO,它们的实现上有什么区别吗?如果用protocol和delegate(或者delegate的Array)来实现类似的功能可能吗?如果可能,会有什么潜在的问题?如果不能,为什么?

    答:KVO只能监测属性的变化,通过NSString类型的属性名来实现。但是实现了自动监测,当属性值变化时,会自动通知观察者,不用再添加代码了。

          NSNotification比较灵活,可以监测的内容较多,但是需要被观察者手动发送通知,观察者才能响应。

          protocol通过添加一个NSArray也能实现类似的功能,但是实现上需要自己处理delegate的添加与删除,自己在属性变化时手动通知,较繁琐,易出错

通知机制简介

/**

 *  NSNotificationCenter 两个对象之间传递消息,或者多个对象之间传递消息

 *  a 对象触发了某个事件(a对象不能完成),需要b对象完成,a对象(void)postNotificationName:(NSString *)aName object:(id)anObject;

 *  postNotificationName 发送消息的名字

 *  object 发送给哪个对象

 *  - (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject; 谁接收通知,接收到通知后实现的方法(SEL)aSelector 

 *  removeObserver移除通知

 */

    下面的KVO的Demo代码:

 

  1 Person.h内容
  2 
  3 #import <Foundation/Foundation.h>
  4 
  5 @interface Person : NSObject
  6 
  7 @property (nonatomic , copy) NSString *name;
  8 @property (nonatomic , assign) int  age;
  9 
 10 //- (void)dogNameChange;
 11 
 12 //- (void)dogAgeChange;
 13 
 14 @end
 15 
 16 
 17 Person.m文件内容
 18 #import "Person.h"
 19 
 20 @implementation Person
 21 
 22 //监听者实现方法
 23 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 24 {
 25     if ([keyPath isEqual:@"name"]) //dog的name属性改变了
 26     {
 27         NSLog(@"Dog - name- change,old:%@ ,new:%@;context = %@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey],context);
 28         
 29     }
 30     
 31     if ([keyPath isEqual:@"age"]) //dog的age属性改变了
 32     {
 33         NSLog(@"Dog - age - change,old:%@ ,new:%@;context = %@",[change objectForKey:NSKeyValueChangeOldKey],[change objectForKey:NSKeyValueChangeNewKey],context);
 34     }
 35 }
 36 
 37 //- (NSString *)description
 38 //{
 39 //    return [NSString stringWithFormat:@"name - %@, age - %d",self.name,self.age];
 40 //}
 41 //
 42 //
 43 //- (void)dogNameChange
 44 //{
 45 //    NSLog(@"dogNameChange");
 46 ////    [self removeObserver:self forKeyPath:@"name"];
 47 //}
 48 //
 49 //- (void)dogAgeChange
 50 //{
 51 //     NSLog(@"dogAgeChange");
 52 //}
 53 
 54 @end
 55 
 56 Dog.h内容
 57 
 58 #import <Foundation/Foundation.h>
 59 
 60 @class Person;
 61 @interface Dog : NSObject
 62 
 63 
 64 @property (nonatomic , weak) Person *onwer;
 65 @property (nonatomic , assign) NSInteger age;
 66 @property (nonatomic , copy) NSString *name;
 67 
 68 @end
 69 
 70 Dog.m内容
 71 
 72 #import "Dog.h"
 73 
 74 @implementation Dog
 75 
 76 
 77 @end
 78 
 79 ViewController.m内容
 80 
 81 #import "SDViewController.h"
 82 #import "Person.h"
 83 #import "Dog.h"
 84 
 85 @implementation SDViewController
 86 
 87 - (void)viewDidLoad
 88 {
 89     [super viewDidLoad];
 90      Person *p = [[Person alloc] init];
 91     p.name = @"张三";
 92     p.age = 18;
 93     
 94     Dog *d = [[Dog alloc] init];
 95     d.age = 10;
 96     d.name = @"老狗";
 97 
 98      //KVO演练 -- 监听某个对象属性的改变
 99     [d addObserver:p forKeyPath:@"age" options:(0x01 | 0x02) context:@"helloage"];
100     [d addObserver:p forKeyPath:@"name" options:(0x01 | 0x02) context:@"helloname"];
101     
102     //KVC赋值
103     [d setValue:@(28) forKeyPath:@"age"];
104     [p setValue:@"李四" forKeyPath:@"name"];
105     [p setValue:@(10) forKeyPath:@"age"];
106     [d setValue:@"小狗狗" forKeyPath:@"name"];
107     
108 //    [d removeObserver:p forKeyPath:@"name"]; //移除KVO
109 //    [d removeObserver:p forKeyPath:@"age"]; //移除KVO
110 
111    
112 }

 

 

 

KVO中的头文件中重要的方法简介

/*由于接收器已经被注册为在相对于物体的关键路径价值的观察者,被通知更改该值。 变更字典总是包含NSKeyValueChangeKindKey项,其值是一个NSNumber包装的NSKeyValueChange(使用 - [NSNumber的unsignedIntegerValue])。 NSKeyValueChange的意义取决于什么样的属性和关键线路识别: - 对于任何类型的属性(属性,以一对一的关系,或有序或无序的一对多关系)NSKeyValueChangeSetting表示该观察对象已经收到了-setValue:forKey:消息,或者说,键 - 值编码兼容的设置方法密钥已被调用,或者一个-willChangeValueForKey:/ - didChangeValueForKey:对以其他方式被调用。 - 对于_ordered_一对多的关系,NSKeyValueChangeInsertion,NSKeyValueChangeRemoval和NSKeyValueChangeReplacement表明,突变的消息已发送到由-mutableArrayValueForKey返回的数组:发送给对象的消息,或者发送到由-mutableOrderedSetValueForKey返回的有序集合:消息发送给对象,或者说,键值中的一个编码标准的阵列或有序集合突变方法的关键已被调用,或者一个-willChange:valuesAtIndexes:forKey:/ - didChange:valuesAtIndexes:forKey:对有否则被调用。 - 对于_unordered_一对多的关系,NSKeyValueChangeInsertion,NSKeyValueChangeRemoval和NSKeyValueChangeReplacement(在Mac OS10.4中引入)表明,突变的消息已发送到由-mutableSetValueForKey返回的集合:发送给对象的消息,或那一个键 - 值编码兼容的一套基因突变的方法对密钥已被调用,或者一个 -willChangeValueForKey:withSetMutation:usingObjects:/-didChangeValueForKey:withSetMutation:usingObjects:对了,否则被调用。 对于任何形式的财产,变更字典有一个NSKeyValueChangeNewKey项,如果NSKeyValueObservingOptionNew在观察者注册时指定,这是正确的一种变化,这是不是事先通知。变更字典包含NSKeyValueChangeOldKey如果指定NSKeyValueObservingOptionOld,这是正确的一种变化。请参阅该NSKeyValueObserverNotification非正式协议的方法是什么这些条目的值可以是评论。 对于一个_ordered_一对多的关系,变更字典总是包含一个NSKeyValueChangeIndexesKey条目的值是包含插入,删除或替换的对象的索引,除非该变化是NSKeyValueChangeSetting一个NSIndexSet。 如果NSKeyValueObservingOptionPrior(中的Mac OS10.5引入)指定在观察者登记时间,而该通知是一个先前被发送到的变化,结果,变更字典包含NSKeyValueChangeNotificationIsPriorKey项,其值被一个NSNumber包装纸是(用 - [NSNumber的boolValue])。 背景始终是在观察者报名时间的推移,在同一个指针。*///监听者实现方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
//注册观察者 -- observer 谁在监听, keyPath -- 监听哪一个属性值 options -- 新的值与旧的值 context -- 传送给observer 的消息
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;

//移除观察者 - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context NS_AVAILABLE(10_7, 5_0); - (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;

  

转载于:https://www.cnblogs.com/ndyBlog/p/3955885.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460101.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

获取win7时区所有信息

打开命令行工具&#xff1a; tzutil /l# 或者输入到文件中tzutil /l > data.txt 1 # -*- utf-8 -*-2 3 """获取win7所有时区信息&#xff0c;并写入到sql语句中4 5 Usage: python data.py -f data.txt -o data.sql6 """7 8 if __name__ &quo…

linux kill命令信号,Linux kill 命令详解

Linux kill 命令很容易让人产生误解&#xff0c;以为它仅仅就是用来杀死进程的。我们来看一下 man page 对它的解释&#xff1a;kill - send a signal to a process.从官方的解释不难看出&#xff0c;kill 是向进程发送信号的命令。当然我们可以向进程发送一个终止运行的信号&a…

VSTO学习笔记(二)Excel对象模型

原文:VSTO学习笔记&#xff08;二&#xff09;Excel对象模型上一次主要学习了VSTO的发展历史及其历代版本的新特性&#xff0c;概述了VSTO对开发人员的帮助和效率提升。从这次开始&#xff0c;将从VSTO 4.0开始&#xff0c;逐一探讨VSTO开发中方方面面&#xff0c;本人接触VSTO…

zen-coding for notepad++,前端最佳手写代码编辑器

zen-Coding是一款快速编写HTML,CSS&#xff08;或其他格式化语言&#xff09;代码的编辑器插件&#xff0c;这个插件可以用缩写方式完成大量重复的编码工作&#xff0c;是web前端从业者的利器。 zen-Coding插件支持多种编辑器&#xff0c;如UltraEdit&#xff0c;Notepad等。 温…

red hat linux 远程,Red Hat Linux 远程桌面 – 如何设置

远程访问 RHEL 计算机。运行 RHEL 7.3-8.1 的 Linux 计算机的远程桌面。从任何计算机、平板电脑或移动设备进行访问。立即免费试用&#xff01;如果您是在家中或在旅途中工作&#xff0c;则可能需要一段时间才能在办公室或在家中访问台式计算机。如果该桌面恰巧在 Linux 操作系…

通过boundingRectWithSize:options:attributes:context:计算文本尺寸

转&#xff1a;http://blog.csdn.net/jymn_chen/article/details/10949279 之前用Text Kit写Reader的时候&#xff0c;在分页时要计算一段文本的尺寸大小&#xff0c;之前使用了NSString类的sizeWithFont:constrainedToSize:lineBreakMode:方法&#xff0c;但是该方法已经被iOS…

H264/AVC视频解码时AVC1和H264的区别

AVC1与H264的区别http://blog.csdn.net/qiuchangyong/article/details/6660253H.264 Video TypesThe following media subtypes are defined for H.264 video.Subtype FOURCC DescriptionMEDIASUBTYPE_AVC1 AVC1 H.264 bitstream without start codes.MEDIASUBTYPE…

Linux命令行显示无效的命令,LINUX 命令ifconfig 无效

在安装完成linux后&#xff0c;进入终端&#xff0c;输入命令行ifconfig&#xff0c;会提示bash: ifconfig: command notfound。这是因为在我们的环境变量里&#xff0c;还没有设置完整变量。如果我们输入/sbin/ifconfig或/usr/bin/gcc就可以执行命令行。为了不输入命令行的完整…

移动后端支持平台Parse将API由Ruby迁移到Go

Charity Majors是移动后端支持平台Parse的工程师。近日&#xff0c;他撰文介绍了他们将API从Ruby迁移到Go的过程。\\2011年&#xff0c;Parse借助Ruby on Rails快速推出了第一个版本。他们用Unicorn作为HTTP服务器&#xff0c;用Capistrano部署代码&#xff0c;用RVM管理环境&a…

面向对象三大特征之继承(extends)——Java笔记(六)

继承&#xff1a;从一般到特殊的关系&#xff0c;是一种拓展关系&#xff0c;子类对象是父类的一种&#xff0c;也可称为”is a“的关系泛化&#xff1a;把子类里的共性抽取到父类里的来的过程特化&#xff1a;子类在父类的基础上上定义了自己特有的行为特征的过程格式&#xf…

linux 虚拟钢琴程序,基于 Linux 与 VS1003 的 MIDI 电子节拍器的设计与实现,为乐器演奏(如钢琴、吉他)...

基于 Linux 与 VS1003 的 MIDI 电子节拍器的设计与实现&#xff0c;为乐器演奏(如钢琴、吉他)2016-08-22 0 0 0 4.0分其他1积分下载如何获取积分&#xff1f;基于 Linux 与 VS1003 的 MIDI 电子节拍器的设计与实现&#xff0c;为乐器演奏(如钢琴、吉他)提供稳定&#xff0c;丰富…

一个从源代码里提取中文字符串的java类

2019独角兽企业重金招聘Python工程师标准>>> 工作中需要优化代码里的中文警示语和异常信息&#xff0c;实在比较多&#xff0c;所以就写了个程序专门从代码里提取中文字符串。 java做的&#xff0c;比较简单&#xff0c;放上来备忘 package com.extractstr.app;impo…

oracle RAC切换归档

&#xff08;转自leshami&#xff09; RAC环境下的归档模式切换与单实例稍有不同&#xff0c;主要是共享存储所产生的差异。在这种情况下&#xff0c;我们可以将RAC数据库切换到非集群状态下&#xff0c;仅仅在一个实例上来实施归档模式切换即可完成RAC数据库的归档模式转换问…

linux启用ipmi服务,使用 ipmitool 实现 Linux 系统下对服务器的 ipmi 管理

简介&#xff1a; IPMI 是一种可扩展的标准&#xff0c;它定义了如何监控硬件和传感器、控制系统部件以及记录重大事件&#xff0c;随着 ipmi 技术在服务器中的应用&#xff0c;利用 ipmi 的众多优势就成为服务器管理特别是集群管理中不可缺少的部分。本文首先介绍了 ipmi 的一…

eclipse 使用指南

eclipse使用指南 eclipse下载地址&#xff1a; 1、eclipse快捷键 2、将eclipse新建项目的默认编码GBK改为UTF-8 3、Java 编程下 Eclipse 如何设置单行代码显示的最大宽度 4、使用Eclipse创建模板并格式化代码5、Java compiler level does not match the version of the install…

sql 创建用户脚本

USE master go CREATE LOGIN jiazhuang --用户名 WITH PASSWORD sa, --密码 DEFAULT_DATABASE JiaZhuan, --数据库名 CHECK_EXPIRATION OFF, CHECK_POLICY OFF go EXEC sp_addsrvrolemember JiaZhuan, sysadmin --角色 go 要想成功访问 SQL Server 数据库中的数据…

linux中bc用法英文,使用GNU bc在Linux Shell中进行数学运算

在 shell 中使用 bc 更好地做算数&#xff0c;它是一种用于高级计算的数学语言。大多数 POSIX 系统带有 GNU bc&#xff0c;这是一种任意精度的数字处理语言。它的语法类似于 C&#xff0c;但是它也支持交互式执行语句和处理来自标准输入(stdin)的数据。因此&#xff0c;它通常…

Linux C Socket编程原理及简单实例

部分转自&#xff1a;http://goodcandle.cnblogs.com/archive/2005/12/10/294652.aspx 1. 什么是TCP/IP、UDP&#xff1f; 2. Socket在哪里呢&#xff1f; 3. Socket是什么呢&#xff1f; 4. 有很多的框架&#xff0c;为什么还在从Socket开始&#xff1f; 5. Linux C…

linux中timer的作用,linux - linux / timer.h setup_timer()到期功能不起作用? - 堆栈内存溢出...

因此&#xff0c;我的setup_timer()中的TimerExpire函数会引起巨大的恐慌(将在下面发布)&#xff0c;而对TimerExpire()的常规函数​​调用实际上将输出我的输入。void TimerExpire(char* data){printk("Timer Data: %s\n", data);}setup_timer(&my_timer, Timer…

蜉蝣极客

蜉蝣极客 百科名片 蜉蝣目&#xff08;英文&#xff1a;mayfly&#xff0c;学名&#xff1a;Ephemeroptera&#xff09;通称蜉蝣&#xff0c;具有古老而特殊的性状&#xff0c;是最原始的有翅昆虫。和蜻蜓目可同分为古翅次纲&#xff0c;他们的翅不能折叠。蜉蝣目昆虫体形细长…