04 KVC|KVO|Delegate|NSNotification区别

一、 iOS 中KVC、KVO、NSNotification、delegate 在实际的编程中运用的非常多,掌握好他们的运行原理和使用场合对于我们程序的开发将会带来事办工倍的效果;

 

二、 KVC  key-Value coding,键值编码,级通过制定的key我们能查找到对应的value,也能给对应的key附上value值。这一点类似于我们的字典查找。比如我们需要查找哪一页的内容,只需要将字典的唯一的页码(也就是key)找到,就能够知道这一页的内容,根据这个字典这一特性,程序猿们发明了Dictionary. 

       setValueForKey

       setValueForUnDefineKey

       setValueForKeys

       通过这些方法我们可以对指定的key赋值,页可以对类中没有定义的key赋值。

       由于这种方式是通过键值查找和赋值的,它不会经过setter和getter方法,同时也可以给id对象进行赋值。

       

//定义一个学生类,学生属性中有一个狗类,书类

#import <Foundation/Foundation.h>
#import "TRDog.h"
@interface TRStrudent : NSObject
{
    @private
    float _score;
}
@property(strong,nonatomic)NSString* name;
@property(strong,nonatomic)TRDog* dog;
@property(strong,nonatomic)NSArray* allBooks;
@end
#import "TRStrudent.h"
#import "TRBook.h"
@implementation TRStrudent
-(instancetype)init
{
    if (self=[super init]) {
        self.dog=[[TRDog alloc]init];
        TRBook* book1=[[TRBook alloc]init];
         book1.bookname=@"language";
        book1.bookprice=100;

        TRBook* book2=[[TRBook alloc]init];
        book2.bookname=@"math";
        book2.bookprice=30;
        self.allBooks=@[book1,book2];
    }
    return self;
}
@end

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface TRBook : NSObject
@property(strong,nonatomic)NSString* bookname;
/*CGFloat可以识别系统的位数*/
@property(assign,nonatomic)CGFloat  bookprice;
@end

#import "TRBook.h"

@implementation TRBook

@end

#import <Foundation/Foundation.h>

@interface TRDog : NSObject
@property(strong,nonatomic)NSString* name;
@end

#import "TRDog.h"

@implementation TRDog

@end
#import "ViewController.h"
#import "TRStrudent.h"
@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    TRStrudent* stu=[[TRStrudent alloc]init];
    /*使用KVC为私有的成员变量赋值*/
    [stu setValue:@98.5 forKey:@"score"];  //@98.5将数据进行了封装
    [stu setValue:@"zhangshan" forKey:@"name"];
    NSLog(@"name%@",[stu valueForKey:@"name"]);
    NSLog(@"score%@",[stu valueForKey:@"score"]);

    /*使用KVC为id类型的对象赋值*/
    id stu2=[[TRStrudent alloc]init];
    [stu2 setValue:@"wangwu" forKey:@"name"];
    NSLog(@"name:%@",[stu2 valueForKey:@"name"]);

    /*使用KVC进行层级访问,为学生的Dog对象赋值*/
    [stu.dog setValue:@"旺财" forKey:@"name"];
    NSLog(@"stu.dog name:%@",stu.dog.name);

    /*KeyPath可以访问带有层级关系的属性*/
    [stu2 setValue:@"阿黄" forKeyPath:@"dog.name"];
    NSLog(@"stu2 dongname:%@",[stu2 valueForKeyPath:@"dog.name"]);

    /*可以使用一些关键字快速返回数组中的某些数据,或对数组中的数据进行运算*/
    NSArray* allBookName=[stu valueForKeyPath:@"allBooks.bookname"];
    NSLog(@"%@",allBookName);

    /*所有书的总价格*/
    NSLog(@"%@",[stu valueForKeyPath:@"[email protected]"]);
    /*学生一共有几本书*/
    NSLog(@"totalbooks%@",[stu valueForKeyPath:@"[email protected]"]);

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

-》通过上面的代码不难看出,使用KVC可以对多个包含关系的key值进行层级访问

[stu2 valueForKeyPath:@"dog.name"]

-》使用KVC可以对数组key所包含的keys对应的value 进行函数运算

       [stu valueForKeyPath:@"[email protected]"]  对allBooks数组中所有的bookPrice的value价格进行了求和

-》使用KVC可以对数组中的key进行计数

[stu valueForKeyPath:@"[email protected]"]   allBooks为一个属性数组,包括了多本书。使用[email protected]进行计数

二、 KVO ,给某个对象的属性keyPath添加观察者,当这个属性发生变化时,检查者能立即知道。常用的的API如下:

1.注册需要观察的对象的属性addObserver:forKeyPath:options:context:
      2.实现observeValueForKeyPath:ofObject:change:context:方法,这个方法当观察的属性变化时会自动调用
      3.取消注册观察removeObserver:forKeyPath:context:

其本质是在在runtime运行时过程中,系统会自动派生出一个新的类NSKVONotifying_TRSudent,在此类中会改写 keyPath的set方法,在里面添加一个方法

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context;   所以只需要在父类中写下这个方法的实现过程,当运行子类派生的set方法时候就会自动的执行此方法。

/**

参数一:被观察的对象

参数二:需要观察的对象

参数三:age 需要观察的对象的对应的属性

参数四:一段属性发生该百年,给监控着发送消息需要传递的值,是否是旧值和新值

参数五:发送的额外信息

*/

[self.stu addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:@"又老了一点"];

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {

id newValue = [object valueForKey:keyPath];

NSLog(@"%@ 对象的%@属性发生了改变\n,数值如下:旧值是%@,新值是:%@,额外信息%@",object,keyPath,change[@"old"],change[@"new"],context);

}

三、 各自的使用时机:

KVO使用时机: 当用户输入的View界面有个地方改变的时候我们希望model层做出一定的响应并将信息反馈出来。 比如我们在需要确认用户输入的新值和旧值的时候来做一定的计算处理。再比如主任的宠物的血量放生变化的时候主人的攻击受到影响。KVO使用会派生新的类,比较耗费程序资源,一般较少使用。

Delegate使用时机:常用用于界面View点击时间中的交互动作,例如系统UI控件被用户点击或拖拽后会出发一些列的响应事件,类似于这种同类型的业务逻辑之间的响应方式,比较适合使用Delegate.由比如一个类对多个类之间有着同样的业务需求,就好比一个老板需要多个秘书来协同处理它交代的任务,这样的场合也比较适合使用代理。代理方和委托方存在has-a的控制关系,执行效率较高,且刻度性较高,缺点主要是代码累赘,规则繁琐。

Block使用时机:与代理功能相似的还有Block,但他的刻度性较差,尤其是出现多重调用的时候很容易让人混淆,所以长使用Block在单一的两个类之间进行回调,例如登录注册请求工具类,登录注册控制器。 地图定位请求工具类,与主控制器请求定位类。 这种比较单一的,简单单的回调可以使用Block.  -》通过对堆区预先注册函数,等到运行到这个block块的时候再调用,使用效率也相对较高,而且比较灵活,缺点可读性差。

NSNotificaiton: 使用实际,它常用于一些系统性的通知,及多个类中都有可能需要对某一信息进行监听,主要是讲通知发送到广播中心,通过第三方媒介广播进行发送通知消息。接收他的对象只需在通知中心进行订阅即可,比较适合于一个控制器要同时监听多个控制器的变化消息。 例如 我们的分类列表栏目里有很多子控制器的分栏列表,当这些个数据发生变化的时候我们需要通知到主控制器进行界面的数据更新,如果都适用协议,就会导致程序编的非常复杂,主控制器中需要遵守各种各样的协议,(如果使用通知,就很方便的管理我们的代码),所有的操作都需要依靠三方来完成,执行效率略逊于代理。

时间: 2024-10-27 06:27:36

04 KVC|KVO|Delegate|NSNotification区别的相关文章

NotificationCenter KVC KVO Delegate总结

KVO(Key-Value- Observing): 一对多, 观察者模式,键值观察机制,它提供了观察某 一属性变化的方法,极大简化了代码. KVO底层实现: - kvo 是基于 runtime 机制实现 - 使用了 isa 混写 isa-swizzling ,当一个对象( 假设是person对象,   person的类是MYPerson)的属性值(假设 person 的 age 属性)发生改变时,系统会自动生成一个类,继承自  MYPerson : NSKVONotifying_MYPerso

iOS 中KVC、KVO、NSNotification、delegate 总结及区别

iOS 中KVC.KVO.NSNotification.delegate 总结及区别 1.KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性.而不是通过调用Setter.Getter方法访问.KVO 就是基于 KVC 实现的关键技术之一. Demo: @interface myPerson : NSObject { NSString*_name; int      _age; int      _height; int      _w

iOS 中KVC、KVO、NSNotification、delegate 总结及区别-b

1.KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性.而不是通过调用Setter.Getter方法访问.KVO 就是基于 KVC 实现的关键技术之一. Demo: @interface myPerson : NSObject { NSString*_name; int      _age; int      _height; int      _weight; } @end @interface testViewController

KVC、KVO、NSNotification、delegate 总结及区别

1.KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性.而不是通过调用Setter.Getter方法访问.KVO 就是基于 KVC 实现的关键技术之一. Demo: @interface myPerson : NSObject { NSString*_name; int      _age; int      _height; int      _weight; } @end @interface testViewController

KVC、KVO、NSNotification、delegate 的区别,对公司新人的解答

delegate 的 优势 : 1.非常严格的语法.所有将听到的事件必须是在delegate协议中有清晰的定义. 2.如果delegate中的一个方法没有实现那么就会出现编译警告/错误 3.协议必须在controller的作用域范围内定义 4.在一个应用中的控制流程是可跟踪的并且是可识别的: 5.在一个控制器中可以定义定义多个不同的协议,每个协议有不同的delegates 6.没有第三方对象要求保持/监视通信过程. 7.能够接收调用的协议方法的返回值.这意味着delegate能够提供反馈信息给c

KVC&amp;KVO&amp;NSNotification

KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性.KVO 就是基于 KVC 实现的关键技术之一. 一个对象拥有某些属性.比如说,一个 Person 对象有一个 name 和一个 age 属性.以 KVC 说法,Person 对象分别有一个 value 对应他的 name 和 address 的 key. key 只是一个字符串,它对应的值可以是任意类型的对象.从最基础的层次上看,KVC 有两个方法:一个是设置 key 的值,另一个

iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)

iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例) 实现了以下iOS页面间传值:1.委托delegate方式:2.通知notification方式:3.block方式:4.UserDefault或者文件方式:5.单例模式方式:6.通过设置属性,实现页面间传值 在iOS开发中,我们经常会遇到页面间跳转传值的问题,现归纳总结一下: 情况1:A页面跳转到B页面 方法: 在B页面的控制器中,编写对应的属性,在A页面跳转到B页面的地方,给

iOS开发笔试面试- KVC/KVO简单使用

转自:http://my.oschina.net/caijunrong/blog/510701 一.对于KVC模式(Key Value Coding): 1.其实在实际开发中用得比较多得就是:接收到json数据之后,通过解析,解析成NSDictionary,然后再把字典对应的字段建立一个Model,在Model里面自定义一个类方法+(instancetype)modelWithDictionary:(NSDictionary *)keyDictionary方法中调用 [self setValue

转:KVC/KVO原理详解及编程指南

作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/9674431 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号wangzzstrive来支持我,谢谢! 前言: 1.本文基本不讲KVC/KVO的用法,只结合网上的资料说说对这种技术的理解. 2.由于KVO内容较少,而且是以KVC为基础实现的,本文将着重介绍KVC部分. 一.简介 KVC/KVO是观察者模式的一种实现,在Cocoa中是以被万物之源NS