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多了发送通知的一步,但是其优点是监听不局限于属性的变化,还可以对多种多样的状态变化进行监听,监听范围广,使用也更灵活。
  • 相关阅读:
    Leetcode 15 3Sum
    Leetcode 383 Ransom Note
    用i个点组成高度为不超过j的二叉树的数量。
    配对问题 小于10 1.3.5
    字符矩阵的旋转 镜面对称 1.2.2
    字符串统计 连续的某个字符的数量 1.1.4
    USACO twofive 没理解
    1002 All Roads Lead to Rome
    USACO 5.5.1 求矩形并的周长
    USACO 5.5.2 字符串的最小表示法
  • 原文地址:https://www.cnblogs.com/linganxiong/p/5864039.html
Copyright © 2011-2022 走看看