KVC 和 KVO
一. KVC
1.KVC介绍
KVC 就是键值编码(key-value-coding)。
2.KVC 的主要作用:
(1)通过键值路径为对象的属性赋值。主要是可以为私有的属性赋值。
AppleViewController *appleVC = [[AppleViewController alloc]init];
[appleVC setValue:@"橘子" forKey:@"name"];
如果对象A的属性是一个对象B,要设置对象B的属性
[person setValue:@"旺财" forKeyPath:@"dog.name"];
(2)通过键值路径获取属性的值。主要是可以通过key获得私有属性的值。
NSString *nameStr = [appleVC valueForKey:@"name"];
也可以通过keypath获得值
NSString *dName = [person valueForKeyPath:@"dog.name"];
(3)将字典转型成Model,方法:setValuesForKeysWithDictionary:

// 定义一个字典
NSDictionary *dict = @{
@"name" : @"jack",
@"money" : @"20.7",
};
// 创建模型
Person *p = [[Person alloc] init]; // 字典转模型
[p setValuesForKeysWithDictionary:dict];
NSLog(@"person's name is the %@",p.name);

注意:字典的key和Model的属性一定要一一对应。否则会出现错误。比如person里没有name的属性,系统报错如下:
'[<Person 0x60000001d0b0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key name.'
(4)常用方法
它提供了一种使用字符串而不是访问器方法去访问一个对象实例变量的机制。
1.通过key(成员变量的名称)设置value(成员变量的值)
- (void)setValue:(id)value forKey:(NSString *)key;
2.通过keyPath(成员变量的路径)设置value(成员变量的值)
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
3.通过key(成员变量的名称)获取value(成员变量的值)
- (id)valueForKey:(NSString *)key;
4.通过keyPath(成员变量的路径)获取value(成员变量的值)
- (id)valueForKeyPath:(NSString *)keyPath;
5.重写此方法防止出现未定义key值的时候出现崩溃
- (void)setValue:(id)value forUndefinedKey:(NSString *)key;
6.重写此方法防止获取未定义key值的时候出现崩溃
- (id)valueForUndefinedKey:(NSString *)key;
7.通过键值对的形式给成员变量赋值
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
举个简单的例子:一个对象拥有某些属性。比如说,一个 Person 对象有一个 perName,uid,perID和一个 sex 属性。以 KVC 说法,Person 对象分别有一个 value 对应他的 perName,uid,perID和一个 sex 的 key。 key 只是一个字符串,它对应的值可以是任意类型的对象。从最基础的层次上看,KVC 有两个方法:一个是设置 key 的值,另一个是获取 key 的值。
#import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatomic,copy)NSString *perName;
@property (nonatomic,copy)NSString *sex;
@property (nonatomic,copy)NSString *uid;
@property (nonatomic,copy)NSString *perID; @end
#import "Person.h" @implementation Person -(void)setValue:(id)value forKey:(NSString *)key{ //判断是否为NSNumber类型
if ([value isKindOfClass:[NSNumber class]]) { [self setValue:[NSString stringWithFormat:@"%@",value] forKey:key]; }else { //调用父类的方法
[super setValue:value forKey:key]; } } -(void)setValue:(id)value forUndefinedKey:(NSString *)key{
//手动赋值
if ([key isEqualToString:@"id"]) { [self setValue:value forKey:@"perID"]; }else{ NSLog(@"未定的key值:%@",key); } } -(id)valueForUndefinedKey:(NSString *)key{ NSLog(@"未找到key:%@",key);
return nil;
} - (NSString *)description
{
return [NSString stringWithFormat:@"name = %@,sex = %@,ID= %@,perID = %@", _perName,_sex,_uid,_perID];
} @end
#import <Foundation/Foundation.h>
#import "Person.h" int main(int argc, const char * argv[]) {
@autoreleasepool { Person *per = [Person new]; //模拟返回的服务器数据
NSDictionary *dictionary = @{@"perName":@"小红",@"sex":@"女",@"uid":[NSNumber numberWithInteger:888],@"id":@"12345"}; //通过KVC一次性给3个成变量赋值
[per setValuesForKeysWithDictionary:dictionary]; NSLog(@" %@",per); }
return 0;
}
========================================
二. KVO
1.KVO介绍:
KVO 是键值观察者(key-value-observing)。KVO提供了一种观察者的机制,通过对某个对象的某个属性添加观察者,当该属性改变,就会调用"observeValueForKeyPath:"方法,为我们提供一个“对象值改变了!”的时机进行一些操作。
2.KVO原理
当某个类的对象第一次被观察时,系统在运行时会创建该类的派生类,改派生类中重写了该对象的setter方法,并且在setter方法中实现了通知的机制。派生类重写了class方法,以“欺骗”外部调用者他就是原先那个类。系统将这个类的isa指针指向新的派生类,因此改对象也就是新的派生类的对象了。因而改对象调用setter就会调用重写的setter,从而激活键值通知机制。此外派生类还重写了delloc方法来释放资源。
3.KVO的使用
(1)给对象的属性添加观察者
[appleVC addObserver:self forKeyPath:@"name" options: NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
注: options: NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld 返回未改变之前的值和改变之后的值 context可以为空
(2)若该属性发生改变,系统自动调用下面的方法:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
//拿到新值/旧值,进行操作
NSLog(@"newValue----%@",change[@"new"]);
NSLog(@"oldValue----%@",change[@"old"]); }

(3)取消监听
-(void)dealloc
{
[person removeObserver:self forKeyPath:@"test"];
}
4.KVO的使用场景
KVO用于监听对象属性的改变。
(1)下拉刷新、下拉加载监听UIScrollView的contentoffsize;
(2)webview混排监听contentsize;
(3)监听模型属性实时更新UI;
(4)监听控制器frame改变,实现抽屉效果。
(5)方法和举例
提供了一种当其它对象属性被修改的时候能通知当前对象的机制
1.添加观察者
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
2.对象被释放之前,要移除观察者,通常写在dealloc函数当中
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
3.当属性值发生变化之后的回调函数
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
监听一个contentSize的例子:点击一个加号会添加10个cell
#import "ViewController.h" @interface ViewController ()<UITableViewDataSource,UITableViewDelegate> @property (nonatomic,assign)NSInteger count;//控制行数
@property (nonatomic,assign)CGSize recordSize;//记录当前UITableView的ContentSize;
@property (weak, nonatomic) IBOutlet UITableView *myTableView; @end @implementation ViewController -(void)dealloc{ //移除观察者
[self.myTableView removeObserver:self forKeyPath:@"contentSize"]; } - (void)viewDidLoad {
[super viewDidLoad]; //观察myTableView的contentSize
[self.myTableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil]; //设置导航栏右侧按钮
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"+" style:UIBarButtonItemStylePlain target:self action:@selector(add)]; self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"__" style:UIBarButtonItemStylePlain target:self action:nil]; } //增加行数
-(void)add{ self.count += 10; //刷新UI
[self.myTableView reloadData];
//self.recordSize = self.myTableView.contentSize; //NSLog(@"%f",self.recordSize.height);
}
#pragma mark- KVO回调方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ //判断是否为对应的观者属性
if ([keyPath isEqualToString:@"contentSize"] && object == self.myTableView) { NSLog(@"%@ %f",change, self.recordSize.height); //记录变化之后的contentSize
self.recordSize = [change[@"new"] CGSizeValue]; } } #pragma mark- UITableView代理
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return self.count;
} -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"]; if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
} cell.textLabel.text = @"哈哈"; return cell; } @end
如果对你有帮助,请关注我哦!
KVC 和 KVO的更多相关文章
- 11. KVC And KVO
1. KVC And KVO 的认识 KVC/KVO是观察者模式的一种实现 KVC全称是Key-value coding,翻译成键值编码.顾名思义,在某种程度上跟map的关系匪浅.它提供了一种使用 ...
- iOS - 详细理解KVC与KVO
详细理解KVC与KVO 在面试的时候,KVC与KVO有些时候还是会问到的,并且他们都是Objective C的关键概念,在这里我们先做一个简单地介绍: (一)KVC: KVC即指:NSKeyValue ...
- KVC 与 KVO 理解
KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解. Key-Value Coding (KVC) KVC,即是指 NSKeyValueCoding,一 ...
- 【原】iOS中KVC和KVO的区别
在iOS开发中经常会看到KVC和KVO这两个概念,比较可能混淆,特地区分一下 KVC(Key Value Coding) 1> 概述 KVC:Key Value Coding,键值编码,是一种间 ...
- IOS之KVC和KVO(未完待续)
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- KVC和KVO的区别
kvc和kvo 1.kvc Key-Value Coding (KVC) KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性.KVO 就 ...
- 谈KVC、KVO(重点观察者模式)机制编程
一不小心,小明在<跟着贝尔去冒险>这个真人秀节目中看到了“一日警察,一世警察”的Laughing哥,整个节目除了贝尔吃牛睾丸都不用刀叉的不雅餐饮文化外,还是镜头少普通话跟小明一样烂的Lau ...
- iOS中关于KVC与KVO知识点
iOS中关于KVC与KVO知识点 iOS中关于KVC与KVO知识点 一.简介 KVC/KVO是观察者模式的一种实现,在Cocoa中是以被万物之源NSObject类实现的NSKeyValueCodin ...
- 聊聊 KVC 和 KVO 的高阶应用
KVC, KVO 作为一种魔法贯穿日常Cocoa开发,笔者原先是准备写一篇对其的全面总结,可网络上对其的表面介绍已经够多了,除去基本层面的使用,笔者跟大家谈下平常在网络上没有提及的KVC, KVO进阶 ...
- KVC 与 KVO 理解-b
KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解. Key-Value Coding (KVC) KVC,即是指 NSKeyValueCoding,一 ...
随机推荐
- PHP核心技术与最佳实践——全局浏览
难得买到并喜欢一本好书,‘PHP核心技术与最佳实践’. 几天时间,先看了个大概,总结一下整体是什么样子的,怎么看怎么学. 1.总共14章: 2.第1.2章讲PHP的OOP: 其中第一章侧重于PHP的O ...
- 基于Vue.js的表格分页组件
有一段时间没更新文章了,主要是因为自己一直在忙着学习新的东西而忘记分享了,实在惭愧. 这不,大半夜发文更一篇文章,分享一个自己编写的一个Vue的小组件,名叫BootPage. 不了解Vue.js的童鞋 ...
- USACO . Friday the Thirteenth
Friday the Thirteenth Is Friday the 13th really an unusual event? That is, does the 13th of the mont ...
- java jdbc的优化之BeanUtils组件
1. BeanUtils组件 1.1 简介 程序中对javabean的操作很频繁, 所以apache提供了一套开源的api,方便对javabean的操作!即BeanUtils组件. BeanUtils ...
- Angularjs+node+Mysql实现地图上的多点标注
注:本文适合对于node有一定基础的人,如果您是小白,请先用1个小时学习node.node文档https://nodejs.org/en/docs/ 该片博文的源码地址:https://github. ...
- UDP Server
//UDP服务器端程序,可以接受广播,不可接受多播,多播需要join播地址@Override public void run() { while (true) { try { DatagramSock ...
- 关于SQL注入和如何防止
之前在笔试的时候没有很好的答出这个问题,因此我要总结一下问题,以免日后继续在这个地方跌倒,以下是自己的理解,如有错误请指出 一.什么是SQL注入 SQL注入就是服务器在根据业务去处理数据库的时候,客户 ...
- word中表格加粗某一行
选中表格后选择线条粗细. 然后重新绘制一遍就行了.
- 2016福州大学软件工程第三次个人作业-K米软件产品评测
K米软件测评个人作业结果统计如下: 评分标准: 按照栋哥布置的第三次个人作业--K米测评制定评分标准如下: 第一部分:调研.评测 下载并使用,描述最简单直观的个人第一次上手体验. 0.5 按照描述的b ...
- Android开发笔记之《特斯拉-Tesla 代码分析》
转载请注明出处 一.反编译APK文件,查看包结构 // Android库,不多解释android.support // HttpClient 4.1 repackaged for Android // ...