ios kvc和kvo,kvc和kvo是什么东东

1,kvc和kvo是什么东东KVC是一种间接访问对象属性(用字符串表征)的机制,而不是直接调用对象的accessor方法或是直接访问成员对象百度上有- - 我不懂- -希望采纳
2 , ios中KVO和KVC是什么一、KVO是注册观察者模式 , 是一种监听模式 。(1)通过注册观察者addObserve的方法 , 可以获取监听的对象变化的值,从而实现要变化的方法 。(2)例如有两个滑动视图,希望其中一个视图滑动时候 , 另一个视图也跟着变化,同时变化相同的偏移量,那么可以注册一个观察者,观察视图1的偏移量变化,在观察者方法-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context中,根据change的值获得视图1的偏移量,并让视图二做出相同的偏移 。二、KVC是访问对象属性的方法,K即key , V即Value,C是coding系统的编码方式 。(1)通过setValue:forKey的方式,给对象的某一个属性赋值,在未公开属性的情况下就可以使用这种方法.(2)比如有一个Person类,有一个Person *person = [[Person alloc] init]对象,想给个name属性,并给name一个值“张三”,就可以写成[person setValue:"张三" forKey:"name"],如果说person又一个公开的name属性,那么上一句话就等于person.name=@"张三" 。
3 , ios中KVO和KVC是什么一、KVO是注册观察者模式,是一种监听模式 。(1)通过注册观察者addObserve的方法,可以获取监听的对象变化的值,从而实现要变化的方法 。(2)例如有两个滑动视图,希望其中一个视图滑动时候,另一个视图也跟着变化 , 同时变化相同的偏移量,那么可以注册一个观察者,观察视图1的偏移量变化,在观察者方法-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void *)context中,根据change的值获得视图1的偏移量 , 并让视图二做出相同的偏移 。二、KVC是访问对象属性的方法,K即key,V即Value,C是coding系统的编码方式 。(1)通过setValue:forKey的方式,给对象的某一个属性赋值,在未公开属性的情况下就可以使用这种方法. (2)比如有一个Person类 , 有一个Person *person = [[Person alloc] init]对象,想给个name属性,并给name一个值“张三”,就可以写成[person setValue:"张三" forKey:"name"],如果说person又一个公开的name属性 , 那么上一句话就等于person.name=@"张三" 。http://www.mamicode.com/info-detail-515516.htmlkvo是监听(比如某个值变化了 就会调用个方法通知 。具体百度下 好多列子) kvc好像说的是访问对象属性 这个项目中没用到过 据说是鸡肋 。。。【ios kvc和kvo,kvc和kvo是什么东东】
4,iOS 设计模式五KVO 详解KVO 的全称是 Key-Value Observing , 俗称“键值观察/监听”,是苹果提供的一套事件通知机制,允许一个对象观察/监听另一个对象指定属性值的改变 。当被观察对象属性值发生改变时,会触发 KVO 的监听方法来通知观察者 。KVO 是在 MVC 应用程序中的各层之间进行通信的一种特别有用的技术 。KVO 和NSNotification都是 iOS 中观察者模式的一种实现 。KVO 可以监听单个属性的变化,也可以监听集合对象的变化 。监听集合对象变化时,需要通过 KVC 的mutableArrayValueForKey:等可变代理方法获得集合代理对象,并使用代理对象进行操作,当代理对象的内部对象发生改变时,会触发 KVO 的监听方法 。集合对象包含NSArray和NSSet。先创建一个类,作为要监听的对象 。监听实现KVO 主要用来做键值观察操作,想要一个值发生改变后通知另一个对象,则用 KVO 实现最为合适 。斯坦福大学的 iOS 教程中有一个很经典的案例,通过 KVO 在 Model 和 Controller 之间进行通信 。如图所示:KVO 触发分为自动触发和手动触发两种方式 。如果是监听对象特定属性值的改变,通过以下方式改变属性值会触发 KVO:如果是监听集合对象的改变,需要通过 KVC 的mutableArrayValueForKey:等方法获得代理对象,并使用代理对象进行操作,当代理对象的内部对象发生改变时,会触发 KVO 。集合对象包含NSArray和NSSet。普通对象属性或是成员变量使用:NSArray对象使用:NSSet对象使用:observationInfo属性是NSKeyValueObserving.h文件中系统通过分类给 NSObject 添加的属性 , 所以所有继承于 NSObject 的对象都含有该属性;可以通过observationInfo属性查看被观察对象的全部观察信息,包括observer 、 keyPath 、 options 、 context等 。注册方法addObserver:forKeyPath:options:context:中的context可以传入任意数据,并且可以在监听方法中接收到这个数据 。context作用:标签-区分,可以更精确的确定被观察对象属性,用于继承、 多监听;也可以用来传值 。KVO 只有一个监听回调方法observeValueForKeyPath:ofObject:change:context:,我们通常情况下可以在注册方法中指定context为NULL,并在监听方法中通过object和keyPath来判断触发 KVO 的来源 。但是如果存在继承的情况,比如现在有 Person 类和它的两个子类 Teacher 类和 Student 类,person、teacher 和 student 实例对象都对象的 name 属性进行观察 。问题:当 name 发生改变时,应该由谁来处理呢?如果都由 person 来处理,那么在 Person 类的监听方法中又该怎么判断是自己的事务还是子类对象的事务呢?这时候通过使用context就可以很好地解决这个问题,在注册方法中为context设置一个独一无二的值,然后在监听方法中对context值进行检验即可 。苹果的推荐用法:用context来精确的确定被观察对象属性,使用唯一命名的静态变量的地址作为context的值 。可以为整个类设置一个context  , 然后在监听方法中通过object和keyPath来确定被观察属性,这样存在继承的情况就可以通过context来判断;也可以为每个被观察对象属性设置不同的context  , 这样使用context就可以精确的确定被观察对象属性 。context优点:嵌套少、性能高、更安全、扩展性强 。context注意点:KVO 可以监听单个属性的变化,也可以监听集合对象的变化 。监听集合对象变化时,需要通过 KVC 的mutableArrayValueForKey:等方法获得代理对象 , 并使用代理对象进行操作,当代理对象的内部对象发生改变时 , 会触发 KVO 的监听方法 。集合对象包含NSArray和NSSet。(注意:如果直接对集合对象进行操作改变,不会触发 KVO 。)可以在被观察对象的类中重写+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key方法来控制 KVO 的自动触发 。如果我们只允许外界观察 person 的 name 属性,可以在 Person 类如下操作 。这样外界就只能观察 name 属性,即使外界注册了对 person 对象其它属性的监听,那么在属性发生改变时也不会触发 KVO 。也可以实现遵循命名规则为+ (BOOL)automaticallyNotifiesObserversOf<Key>的方法来单一控制属性的 KVO 自动触发 , <Key> 为属性名(首字母大写) 。使用场景:使用 KVO 监听成员变量值的改变;在某些需要控制监听过程的场景下 。比如:为了尽量减少不必要的触发通知操作,或者当多个更改同时具备的时候才调用属性改变的监听方法 。由于 KVO 的本质,重写setter方法来达到可以通知所有观察者对象的目的 , 所以只有通过setter方法或 KVC 方法去修改属性变量值的时候,才会触发 KVO,直接修改成员变量不会触发 KVO 。当我们要使用 KVO 监听成员变量值改变的时候 , 可以通过在为成员变量赋值的前后手动调用willChangeValueForKey:和didChangeValueForKey:两个方法来手动触发 KVO,如:NSKeyValueObservingOptionPrior (分别在值改变前后触发方法 , 即一次修改有两次触发)的两次触发分别在willChangeValueForKey:和didChangeValueForKey:的时候进行的 。如果注册方法中options传入NSKeyValueObservingOptionPrior  , 那么可以通过只调用willChangeValueForKey:来触发改变前的那次 KVO,可以用于在属性值即将更改前做一些操作 。有时候我们可能会有这样的需求 , KVO 监听的属性值修改前后相等的时候,不触发 KVO 的监听方法,可以结合 KVO 的自动触发控制和手动触发来实现 。例如:对 person 对象的 name 属性注册了 KVO 监听 , 我们希望在对 name 属性赋值时做一个判断 , 如果新值和旧值相等,则不触发 KVO,可以在 Person 类中如下这样实现,将 name 属性值改变的 KVO 触发方式由自动触发改为手动触发 。有些情况下我们想手动观察集合属性,下面以观察数组为例 。关键方法:需要注意的是,根据 KVC 的NSMutableArray搜索模式:有些情况下 , 一个属性的改变依赖于别的一个或多个属性的改变,也就是说当别的属性改了,这个属性也会跟着改变 。比如我们想要对 Download 类中的 downloadProgress 属性进行 KVO 监听 , 该属性的改变依赖于 writtenData 和 totalData 属性的改变 。观察者监听了 downloadProgress ,当 writtenData 和 totalData 属性值改变时,观察者也应该被通知 。以下有两种方法可以解决这个问题 。以上两个方法可以同时存在,且都会调用,但是最终结果会以keyPathsForValuesAffectingValueForKey:为准 。以上方法在观察集合属性时就不管用了 。例如,假如你有一个 Department 类,它有一个装有 Employee 类的实例对象的数组,Employee 类有 salary 属性 。你希望 Department 类有一个 totalSalary 属性来计算所有员工的薪水,也就是在这个关系中 Department 的 totalSalary 依赖于所有 Employee 实例对象的 salary 属性 。以下有两种方法可以解决这个问题 。有时候我们难以避免多次注册和移除相同的 KVO,或者移除了一个未注册的观察者,从而产生可能会导致 Crash 的风险 。三种解决方案: 黑科技防止多次添加删除KVO出现的问题我们在对象添加监听之前分别打印对象类型我们看到,添加监听后,使用object_getClass方法获取model类型时获取到的是NSKVONotifying_DJModel。这里就产生了几个问题:从打印结果可以看出, NSKVONotifying_DJModel是DJModel的子类 , 说明我们添加了监听之后动态创建了一个DJModel的子类NSKVONotifying_DJModel  , 并将对象DJModel 的类型更改为了NSKVONotifying_DJModel。我们从源码看出,实例对象调用class方法会返回isa指针,类对象调用class方法会返回自己,通过object_getClass方法获取对象的类型也会返回isa指针 。从源码上看model对象添加监听之后使用class和使用object_getClass方法获取到的类型应该是一样的,但是这里却不同,我们猜测在添加了监听之后在NSKVONotifying_DJModel中重写了class方法 。我们打印一下添加监听前后class方法的IMP地址来确认是否重写了 class方法 。从打印结果可以看出 , 添加监听之后class方法的地址改变了,这验证了我们之前的猜想 ,  NSKVONotifying_DJModel类中重写了class方法 。我们监听对象时调用了set方法,我们对监听前后的set方法单独分析 。我们再添加监听前后分别打印setName方法的IMP 地址 。通过打印结果可以看出setName方法也在NSKVONotifying_DJModel中被重写了 , 我们再使用lldb来看下setName具体是什么第一个地址打印的是添加监听前setName方法的IMP地址,第二个打印的是添加监听后setName方法的IMP地址 。这里看出添加监听前setName对应的具体方法就是setName,但是添加监听后,setName对应的鸡头方法却变成了_NSSetObjectValueAndNotify函数 。下面我们就来研究一下_NSSetObjectValueAndNotify函数 。从上面与KVO相关的方法中我们可以看出,每一种数据类型都对应了一个setXXXValueAndNotify函数 。不过这些函数的具体实现没有公布,所以内部构造这里还是不清楚 。但是我们知道,在调用 `setXXXValueAndNotify 函数的过程中会调用另外两个方法 。测试后得出了以下几个结论:我们还可以利用这两个方法手动触发observeValueForKeyPath方法:所以我们判断在_NSSetObjectValueAndNotify函数内部 , 在调用原来的set方法之前插入了willChangeValueForKey方法,在调用原来的set方法之后插入了didChangeValueForKey方法,并根据初始化时的枚举值决定调用observeValueForKeyPath的时机 。(1)添加监听时 , 会动态创建一个监听对象类型的子类 , 并将监听对象的isa指针指向新的子类 。(2)子类中重写了class和监听属性的set方法 。(3)重写class方法是为了不将动态创建的类型暴露出来 。(4)重写set方法是将set方法的具体实现替换成了与属性类型相关的__NSSetXXXValueAndNotify函数 。(5)在__NSSetXXXValueAndNotify函数内部在set方法前后分别插入了willChangeValueForKey和didChangeValueForKey这两个方法 。(6)根据添加监听时的枚举值决定调用observeValueForKeyPath的具体时机 。5,ios nsnotification和kvo的区别和用法是什么【NSNotification、delegate和KVO的区别】1.效率肯定是delegate比nsnotification高 。2. delegate方法比notification更加直接,最典型的特征是,delegate方法往往需要关注返回值, 也就是delegate方法的结果 。比如-windowShouldClose:,需要关心返回的是yes还是no 。所以delegate方法往往包含 should这个很传神的词 。也就是好比你做我的delegate,我会问你我想关闭窗口你愿意吗?你需要给我一个答案,我根据你的答案来决定如何做下一 步 。相反的 , notification最大的特色就是不关心接受者的态度, 我只管把通告放出来,你接受不接受就是你的事情,同时我也不关心结果 。所以notification往往用did这个词汇,比如 NSWindowDidResizeNotification , 那么nswindow对象放出这个notification后就什么都不管了也不会等待接 受者的反应 。简明概要的说明了KVO和NSNotification的区别:和delegate一样,KVO和NSNotification的作用也是类与类之间的通信,与delegate不同的是1)这两个都是负责发出通知,剩下的事情就不管了,所以没有返回值;2)delegate只是一对一 , 而这两个可以一对多 。这两者也有各自的特点 。1)KVO的使用:被观察者发出 addObserver:forKeyPath:options:context: 方法来添加观察者 。然后只要被观察者的keyPath值变化(注意:单纯改变其值不会调用此方法,只有通过getters和setters来改变值才会触发KVO),就会在观察者里调用方法observeValueForKeyPath:ofObject:change:context:因此观察者需要实现方法 observeValueForKeyPath:ofObject:change:context: 来对KVO发出的通知做出响应 。这 些代码都只需在观察者里进行实现,被观察者不用添加任何代码,所以谁要监听谁注册 , 然后对响应进行处理即可,使得观察者与被观察者完全解耦,运用很灵活很 简便;但是KVO只能检测类中的属性,并且属性名都是通过NSString来查找,编译器不会帮你检错和补全 , 纯手敲所以比较容易出错 。2)NSNotification的使用这里的通知不是由被观察者发出,而是由NSNotificationCenter来统一发出,而不同通知通过唯一的通知标识名notificationName来区分,标识名由发送通知的类来起 。首先被观察者自己在必要的方法A里,通过方法postNotificationName:object:来发出通知notificationName这样发送通知者这边的工作就完成了,每次A被调用,就会发送一次通知notificationName 。然后谁要监听A的变化,就通过[NSNotificationCenter defaultCenter]的方法addObserver:selector:name:object:为观察者注册监听name为notificationName的通知然后每次发出name为notificationName的通知时,注册监听后的观察者就会调用其自己定义的方法notificationSelector来进行响应 。NSNotification的特点呢,就是需要被观察者先主动发出通知,然后观察者注册监听后再来进行响应,比KVO多了发送通知的一步,但是其优点是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听 , 监听范围广,使用也更灵活 。6 , 通知和kvo分别在什么时候使用iOS 中KVC、KVO、NSNotification、delegate 总结及区别1、KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性 。而不是通过调用Setter、Getter方法访问 。KVO 就是基于 KVC 实现的关键技术之一 。Demo:@interface myPerson : NSObjectNSString*_name;int_age;int_height;int_weight;} @end@interface testViewController :UIViewController @property (nonatomic, retain) myPerson*testPerson; @end- (void)testKVCtestPerson = [[myPerson alloc] init];NSLog(@"testPersons init height =%@", [testPerson valueForKey:@"height"]);[testPerson setValue:[NSNumber numberWithInt:168]forKey:@"height"];NSLog(@"testPersons height = %@", [testPerson valueForKey:@"height"]);}第一段代码是定义了一个myPerson的类,这个类有一个_height的属性,但是没有提供任何getter/setter的访问方法 。同时在testViewController这个类里面有一个myPerson的对象指针 。当myPerson实例化后,常规来说是无法访问这个对象的_height属性的,不过通过KVC我们做到了 , 代码就是testKVC这个函数 。运行之后打印值就是:2015-3-13 11:16:21.970 test[408:c07] testPersons init height = 02015-3-13 11:16:21.971 test[408:c07] testPersons height = 168这就说明确实读写了_height属性 。KVC的常用方法:- (id)valueForKey:(NSString *)key; -(void)setValue:(id)value forKey:(NSString *)key;valueForKey的方法根据key的值读取对象的属性 , setValue:forKey:是根据key的值来写对象的属性 。注意:(1). key的值必须正确,如果拼写错误,会出现异常(2). 当key的值是没有定义的,valueForUndefinedKey:这个方法会被调用,如果你自己写了这个方法,key的值出错就会调用到这里来(3). 因为类key反复嵌套 , 所以有个keyPath的概念,keyPath就是用.号来把一个一个key链接起来,这样就可以根据这个路径访问下去(4). NSArray/NSSet等都支持KVC2、KVO的是KeyValue Observe的缩写,中文是键值观察 。这是一个典型的观察者模式,观察者在键值改变时会得到通知 。iOS中有个Notification的机制,也可以获得通知 , 但这个机制需要有个Center,相比之下KVO更加简洁而直接 。KVO的使用也很简单,就是简单的3步 。1.注册需要观察的对象的属性addObserver:forKeyPath:options:context:2.实现observeValueForKeyPath:ofObject:change:context:方法,这个方法当观察的属性变化时会自动调用3.取消注册观察removeObserver:forKeyPath:context:Demo:@interface myPerson : NSObjectNSString *_name;int_age;int_height;int_weight;}@end@interface testViewController : UIViewController@property (nonatomic, retain) myPerson *testPerson;- (IBAction)onBtnTest:(id)sender;@end- (void)testKVOtestPerson = [[myPerson alloc] init];[testPerson addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionNew context:nil];}- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)contextif ([keyPath isEqualToString:@"height"])NSLog(@"Height is changed! new=%@", [change valueForKey:NSKeyValueChangeNewKey]);} else[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];}}- (IBAction)onBtnTest:(id)senderint h = [[testPerson valueForKey:@"height"] intValue];[testPerson setValue:[NSNumber numberWithInt:h+1] forKey:@"height"];NSLog(@"person height=%@", [testPerson valueForKey:@"height"]);}- (void)dealloc[testPerson removeObserver:self forKeyPath:@"height" context:nil];[super dealloc];}第一段代码声明了myPerson类,里面有个_height的属性 。在testViewController有一个testPerson的对象指针 。在testKVO这个方法里面,我们注册了testPerson这个对象height属性的观察,这样当testPerson的height属性变化时, 会得到通知 。在这个方法中还通过NSKeyValueObservingOptionNew这个参数要求把新值在dictionary中传递过来 。重写了observeValueForKeyPath:ofObject:change:context:方法,这个方法里的change这个NSDictionary对象包含了相应的值 。需要强调的是KVO的回调要被调用,属性必须是通过KVC的方法来修改的,如果是调用类的其他方法来修改属性 , 这个观察者是不会得到通知的 。支持一下感觉挺不错的

    推荐阅读