一. 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. Unity性能优化(2)-官方教程Diagnosing performance problems using the Profiler window翻译

    本文是Unity官方教程,性能优化系列的第二篇<Diagnosing performance problems using the Profiler window>的简单翻译. 相关文章: ...

  2. BZOJ 3289: Mato的文件管理[莫队算法 树状数组]

    3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 2399  Solved: 988[Submit][Status][Di ...

  3. springMVC注解初步

    一.(补充)视图解析器---XmlViewResolver 作用:分离配置信息. 在视图解析器---BeanNameViewResolver的基础之上进行扩充,新建一个myView.xml分离信息 在 ...

  4. 平常看到的Alt+xx 快捷键用法

    1. 先按Alt, 哪一个菜单对应的字符是有划线的. 2. 输入对应的字符打开相应的菜单, 3 再输入相应的字符打开子菜单

  5. Kinect for Windows SDK开发入门(十九):Kinect Fusion

        Kinect for Windows SDK1.7中引入了Kinect Fusion功能.在1.8的SDK中对该功能进行了改进和强化,Kinect Fusion能够使得我们使用Kinect f ...

  6. 利用StringEscapeUtils对字符串进行各种转义与反转义(Java)

    apache工具包common-lang中有一个很有用的处理字符串的工具类,其中之一就是StringEscapeUtils,这个工具类是在2.3版本以上加上的去的,利用它能很方便的进行html,xml ...

  7. RESTful API 设计指南

    转自:http://www.ruanyifeng.com/blog/2014/05/restful_api.html 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机. ...

  8. iOS开发小技巧 -- tableView-section圆角边框解决方案

    [iOS开发]tableView-section圆角边框解决方案 tableView圆角边框解决方案 iOS 7之前,图下圆角边框很容易设置 iOS 7之后,tableviewcell的风格不再是圆角 ...

  9. hadoop配置

    配置参考博客:(目前有问题,百度说官网的是32bit,现在正在尝试64位 http://www.powerxing.com/install-hadoop-cluster/

  10. .net 项目生成时自动更新版本号

    https://www.codeproject.com/articles/31236/how-to-update-assembly-version-number-automaticall Exampl ...