zoukankan      html  css  js  c++  java
  • [转]NSNotification、delegate和KVO、KVC的区别

    1.KVC。

    KVC是一种间接访问对象属性的机制,而不是直接通过设置器和访问器或者点语法来访问对象属性。

    比如:创建一个学生对象。

    Student * student = [[Student alloc] init];

    [student setValue@"zhangsan"forKey@"_name"];//通过KVO对student对象的_name变量赋值

    NSString * str = [student valueForKey@"_name"];//取出_name的数值,存放在str中

    还有一种方法。比如在又定义了一个Teacher类。Teacher类里边同样有一个实例变量_name,在Student类的interface中引入Teacher类,并且创建实例变量Teacher  * _t;

    #import <Foundation/Foundation.h>
    //#import "Teach.h"
    @class Teach;//用这样的方法是为了防止执行到引入的时候发生嵌套,产生死循环。
    @interface Student : NSObject
    {
        NSString * _name;    
        Teach * _t;
    }
    @end

    Teacherl类的interface。

    @interface Teach : NSObject
    {
        NSString * _name;
        NSString * _address;
    }
    @end

    在主函数中。

    Teacher * teacher  = [[Teacher alloc] init];//创建一个teacher对象。

    [student setValue@"teacher"forKey@"_t"];//次数的teacher对象是上边刚刚创建的那个teacher对象

    [student setValue@"lisi"ForKeyPath@"_t.name"];//表示路径

    NSString * str1 = [student valueForKeyPath@"_t.name"];//通过student来存取teacher中的变量_name.

    NSString * str2 = [teacher valueForKey@"_name"];//当输出str2的时候结果和str1是相同的都是“lisi”。

    2.KVO。

    当对象的某一个属性发生变化的时候,我们得到一个相应的通知。

    主函数中: 

    Teach * teacher = [[Teach alloc]init];
        teacher.name = @"abc";//在声明文件中声明了name属性。所以直接使用点语法赋值
        [teacher addObserver:teacher   //teacher为事件的监听者,此处就是注意谁监听谁实现后边的 监听触发以后的方法。
                  forKeyPath:@"name" //便是监听的哪一个属性
                  options:NSKeyValueObservingOptionNew |NSKeyValueObservingOptionOld//得到什么值
                  context:nil];
        teacher.name = @"123";//一旦name发生变换,就进入到teacher的实现文件(.m)中调用方法
        teacher.name = @"456";//每次都会调用那个方法,,实时更新

    在Teacher类的.m文件中

    #import "Teach.h"
    @implementation Teach
    @synthesize  name = _name;
     -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
        NSLog(@"keyPath:%@, object:%@  change:%@  context:%@",keyPath,object,change,context);
    }
    @end
    打印结果:

    2012-08-13 08:48:34.162 KVC[422:14503] keyPath:name, object:<Teach: 0x8a3ee10>  change:{
        kind = 1;
        new = 123;  
        old = abc;
    }  context:(null)
    2012-08-13 08:48:34.164 KVC[422:14503] keyPath:name, object:<Teach: 0x8a3ee10>  change:{
        kind = 1;
        new = 456;
        old = 123;
    }  context:(null)

    3.NSNotification 通知

    NSNotification的对象很简单,就是poster要提供给observer的信息包裹。

    在主函数中创建监听通知的过程。

    NSNotificationCenter * center = [NSNotificationCenter defaultCenter];//通过单例得到通知中心,相当于通知在什么地方发布(黑板)

    Teach * teacher = [[Teach alloc]init];

    [center addObserver: teacher  selector:@selector(test:) name:@"黑苹果" object:nil];//self是监听者,selector是表示监听到一个通知以后需要执行里边的test:方法。name表示需要监听的通知是什么内容。object表示监听通知的发出者。

    NSNotification * notification1 = [NSNotification notificationWithName:@"黑苹果" object:teacher  userInfo:nil];创建一个通知

    [center postNotification:notification]//通过上边建立的通知中心center发布通知notification1.

    [center postNotificationWithName:@"黑苹果" object:teacher  userInfo:nil]//作用相当于上边2行代码。

    在监听者teacher的.m文件加加入test:方法

    -(void)test:(NSNotification *)n
    {
        NSLog(@"name : %@  boject = %@  userInfo = %@",[n name],[n object],[n userInfo]);
    }
    打印结果:

    2012-08-13 09:13:35.328 KVC[452:14503] name : 黑苹果  boject = <Teach: 0x6b2b350>  userInfo = (null)

    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多了发送通知的一步,但是其优点是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听,监听范围广,使用也更灵活。
  • 相关阅读:
    Atitit 图像处理30大经典算法attilax总结
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 源码实现attilax总结
    Atitit  rgb yuv  hsv HSL 模式和 HSV(HSB) 图像色彩空间的区别
    Atitit  从 RGB 到 HSL 或 HSV 的转换
    Atitit 图像清晰度 模糊度 检测 识别 评价算法 原理
    Atitit 修改密码的功能流程设计 attilax总结
    atitit 点播系统 概览 v2 qb1.docx
    Atitit dsl exer v3 qb3 新特性
    atitit.TokenService v3 qb1  token服务模块的设计 新特性.docx
    Atitit 异常机制与异常处理的原理与概论
  • 原文地址:https://www.cnblogs.com/linganxiong/p/5864039.html
Copyright © 2011-2022 走看看