一. 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的更多相关文章

  1. 11. KVC And KVO

    1. KVC And KVO  的认识 KVC/KVO是观察者模式的一种实现  KVC全称是Key-value coding,翻译成键值编码.顾名思义,在某种程度上跟map的关系匪浅.它提供了一种使用 ...

  2. iOS - 详细理解KVC与KVO

    详细理解KVC与KVO 在面试的时候,KVC与KVO有些时候还是会问到的,并且他们都是Objective C的关键概念,在这里我们先做一个简单地介绍: (一)KVC: KVC即指:NSKeyValue ...

  3. KVC 与 KVO 理解

    KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解. Key-Value Coding (KVC) KVC,即是指 NSKeyValueCoding,一 ...

  4. 【原】iOS中KVC和KVO的区别

    在iOS开发中经常会看到KVC和KVO这两个概念,比较可能混淆,特地区分一下 KVC(Key Value Coding) 1> 概述 KVC:Key Value Coding,键值编码,是一种间 ...

  5. IOS之KVC和KVO(未完待续)

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  6. KVC和KVO的区别

    kvc和kvo 1.kvc Key-Value Coding (KVC) KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性.KVO 就 ...

  7. 谈KVC、KVO(重点观察者模式)机制编程

    一不小心,小明在<跟着贝尔去冒险>这个真人秀节目中看到了“一日警察,一世警察”的Laughing哥,整个节目除了贝尔吃牛睾丸都不用刀叉的不雅餐饮文化外,还是镜头少普通话跟小明一样烂的Lau ...

  8. iOS中关于KVC与KVO知识点

    iOS中关于KVC与KVO知识点 iOS中关于KVC与KVO知识点  一.简介 KVC/KVO是观察者模式的一种实现,在Cocoa中是以被万物之源NSObject类实现的NSKeyValueCodin ...

  9. 聊聊 KVC 和 KVO 的高阶应用

    KVC, KVO 作为一种魔法贯穿日常Cocoa开发,笔者原先是准备写一篇对其的全面总结,可网络上对其的表面介绍已经够多了,除去基本层面的使用,笔者跟大家谈下平常在网络上没有提及的KVC, KVO进阶 ...

  10. KVC 与 KVO 理解-b

    KVC 与 KVO 是 Objective C 的关键概念,个人认为必须理解的东西,下面是实例讲解. Key-Value Coding (KVC) KVC,即是指 NSKeyValueCoding,一 ...

随机推荐

  1. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  2. 用字体在网页中画Icon图标

    第一步,下载.IcoMoon网站选择字体图标并下载,解压后将fonts文件夹放在工程目录下.fonts文件夹内有四种格式的字体文件: 注:由于浏览器对每种字体的支持程度不一致,要想在所有浏览器中都显示 ...

  3. 如何把select默认的小三角替换成自己的图片

    不同的浏览器默认的select的选项图标是不同的,例如: 在chrome中,是这样的: 未点击时    点击时  在Firefox中是这样的: 未点击时  点击时   在IE9中是这样的: 未点击时  ...

  4. phoneGap+cordova+ionic混合app开发环境搭建

    参考链接:http://www.w2  bc.com/article/177257 待补充

  5. CentOS 7.0 使用 yum 安装 MariaDB 与 MariaDB 的简单配置

    1.安装MariaDB 安装命令 yum -y install mariadb mariadb-server 安装完成MariaDB,首先启动MariaDB,两条命令都可以 systemctl sta ...

  6. Beta版本冲刺计划及安排

    经过紧张的Alpha阶段,很多组已经从完全不熟悉语言和环境,到现在能够实现初步的功能.下一阶段即将加快编码进度,完成系统功能.强化软件工程的体会.Beta阶段的冲刺时间为期七天,安排在2016.12. ...

  7. Babel:JavaScript编译器

    一.介绍: Babel是一个Javascript编译器,可以将ES6语法转换成ES5. 这意味着,你可以现在就用ES6编写程序,而不用担心现有环境是否支持.下面是一个例子: //转码前: input. ...

  8. jq封装淘宝图片轮播插件

    <!DOCTYPE html><head><meta http-equiv="Content-Type" content="text/htm ...

  9. mysql 多版本并发控制

    查看事务隔离级别 SHOW VARIABLES LIKE "%iso%" MVCC 通过给每张表多加两个隐藏列来实现,一个保存了行的创建时间,一个保存了行的过期时间(或删除时间), ...

  10. Spring Boot

    Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过 ...