|KVC的用法

1、KVC既键值编码(Key Value Coding),基于NSKeyValueCoding协议,它是以字符串的形式来操作对象的成员变量,也就是通过字符串key来指定要操作的成员变量。基本操作如:

  • setValue:forKey:为成员变量赋值。如:[student setValue:@"大明" forKey:@"name"];
  • valueForKey:获取指定的成员变量。如:NSString *name = [student valueForKey:@"name"];

2、用KVC操作成员变量的底层实现,就拿成员变量name来说吧,一般按如下顺序执行:

  • 程序先尝试调用name的setter或getter方法,就是先调用setName或name方法来设置或获取成员变量。
  • 如果该类没有提供setter或者getter方法,则KVC机制将会搜索该类中名为_name的成员变量。这时无论该成员变量定义在接口部分还是实现部分,KVC的代码底层都会对_name进行赋值或者获取操作。
  • 如果该类既没有setter或者getter方法,也没有_name成员变量,则KVC机制将会搜索该类中名为name的成员变量。这时无论该成员变量定义在接口部分还是实现部分,KVC的代码底层都会对name进行赋值或者获取操作。
  • 如果以上3步都没能找到指定的成员变量,则程序将会执行setValue:forUndefinedKey:或者valueForUndefinedKey:方法抛出异常,默认是终止程序。

3、对于不存在的key怎么处理呢?默认情况下会抛出NSUnknownKeyException异常,并终止程序。

此时可以直接在类的实现部分重写setValue:forUndefinedKey:和valueForUndefinedKey:方法,当KVC找不到指定的成员变量时,会调用这两个方法,通过重写这两个方法可以方便的定制自己的处理方案。

4、setNilValueForKey:方法的调用。

当用KVC的方式把基本数据类型(如int、float等)设置为nil时,会调用成员变量所属类的setNilValueForKey:方法,抛出NSInvalidArgumentException异常,并终止程序。

此时在该类的实现中重写setNilValueForKey:做相应的处理即可。

5、KVC操作对象的复合属性。

复合属性:一个类的属性是另一个类的对象,这个对象的属性就是就是复合属性,比如Person类有个Student类型的属性student,Student类有个name属性,name相对于Person类就是个复合属性。这个复合属性在KVC机制中被称为key路径,即student.name。

在KVC机制中操作key路径的方法如下:

  • setValue:forKeyPath:根据key路径设置属性值。
  • valueForKeyPath:根据key路径获取属性值。

通过KVC操作对象的性能比通过setter和getter方法要差,但是通过KVC比较灵活。

|KVO的用法

KVO即键值监听(Key Value Observe),基于NSKeyValueObserving协议,用于监听属性值的改变(通常是数据模型)。

KVO的用法分三步:

  1. 为对象指定的key路径注册监听器 -> addObserver:forKeyPath:options:context:。
  2. 重写监听方法以得到最新修改的数据 -> observeValueForKeyPath:ofObject:change:context:。
  3. 删除指定key路径的监听器 -> removeObserver:forKeyPah:或者removeObserver:forKeyPath:context。

参数说明:

observer: 观察对象。

forKeyPath:对象的复合属性。

options分别是:

  • NSKeyValueObservingOptionNew:把更改之前的值提供给处理方法
  • NSKeyValueObservingOptionOld:把更改之后的值提供给处理方法
  • NSKeyValueObservingOptionInitial:把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值。
  • NSKeyValueObservingOptionPrior:分2次调用,在值改变之前和值改变之后。
  • 0:就代表不带任何参数进去。

context: 可以带入一些参数,其实这个挺好用的,任何类型都可以,自己强转就好了。

change:  字典里的key对应options里的NSKeyValueObservingOptionNew、NSKeyValueObservingOptionOld等。

  •  #import "ViewController.h"
    #import "Person.h"
    #import "Student.h" @interface ViewController ()
    @property (strong, nonatomic) Person *person;
    @property (strong, nonatomic) Student *stu;
    @end @implementation ViewController
    - (void)viewDidLoad {
    [super viewDidLoad];
    Person *person = [[Person alloc] init];
    self.person = person;
    Student *stu = [[Student alloc] init];
    self.stu = stu;
    person.height = 1.5;
    person.student = stu;
    stu.height = 1.0;
    stu.age = ;
    [person addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionNew context:nil];
    [person addObserver:self forKeyPath:@"student.height" options:NSKeyValueObservingOptionNew context:nil];
    [stu addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew context:nil];
    for (int i = ; i < ; i++) {
    [person setValue:@(person.height + i) forKey:@"height"];
    [person setValue:@(person.student.height + i) forKeyPath:@"student.height"];
    [stu setValue:@(stu.age + i) forKey:@"age"];
    } NSLog(@":person.height = %@, stu.height = %@, stu.age = %@", [person valueForKey:@"height"], [person valueForKeyPath:@"student.height"], [stu valueForKey:@"age"]);
    } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    NSLog(@"\n--------------------\n被修改的KeyPath:%@\n被修改的对象:%@\n被修改后的值:%@\n被修改的上下文:%@\n\n\n", keyPath, object, change[NSKeyValueChangeNewKey], context);
    } - (void)dealloc {
    [self.person removeObserver:self forKeyPath:@"height"];
    [self.person removeObserver:self forKeyPath:@"student.height"];
    [self.stu removeObserver:self forKeyPath:@"age"];
    } @end

KVC与KVO的实现原理的更多相关文章

  1. KVC和KVO的理解(底层实现原理)

    1.KVC,即是指 NSKeyValueCoding,一个非正式的Protocol,提供一种机制来间接访问对象的属性.而不是通过调用Setter.Getter方法访问.KVO 就是基于 KVC 实现的 ...

  2. KVC 和 KVO 简单总结

    KVC: key value coding,键值编码.是一种通过使用属性的名称(key)来间接访问对象属性的方法.这个方法可以不用通过 setter/getter 方法来访问对象的属性.该方法使用的实 ...

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

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

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

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

  5. KVC和KVO

    OC中的一个比较有特色的知识点:KVC和KVO 一.KVC操作OC中的KVC操作就和Java中使用反射机制去访问类的private权限的变量,很暴力的,这样做就会破坏类的封装性,本来类中的的priva ...

  6. iOS开发中KVC、KVO简介

    在iOS开发中,KVC和KVO是经常被用到的.可以使用KVC对对象的属性赋值和取得对象的属性值,可以使用KVO监听对象属性值的变化.简单介绍一下KVC和KVO. 一:键值编码(KVC) KVC,全称 ...

  7. iOS KVC 和 KVO 区别简单总结

    KVC: key value coding,键值编码.是一种通过使用属性的名称(key)来间接访问对象属性的方法.这个方法可以不用通过 setter/getter 方法来访问对象的属性.该方法使用的实 ...

  8. KVC、KVO实现过程

    1.KVC的实现过程 以 [object setValue:@"134567" forKey:@"uid"];为例子,来探究KVC的实现过程 第一步:搜索1.首 ...

  9. iOS KVC 和 KVO 的学习

    KVC  (NSKey Value Coding) :键值编码 KVO (Key Value Observing) :键值监听 前言:我曾经用过 监听 一个音频何时结束 监听视频播放 状态等 用了这种 ...

随机推荐

  1. HTML基础—插曲

    HTML基础学习 1:我们在网上添加图片的时候最好是缩略图,而不是直接在代码中限制图片的大小.可以为了用户减少流量.Alt=""属性是为了让图片在现实不出来时显示的文字,Title ...

  2. for of 与 for in的区别

    遍历数组通常使用for循环,ES5的话也可以使用forEach,ES5具有遍历数组功能的还有map.filter.some.every.reduce.reduceRight等,只不过他们的返回结果不一 ...

  3. 使用LinkedList模拟一个堆栈或者队列数据结构

    使用LinkedList模拟一个堆栈或者队列数据结构. 堆栈:先进后出  如同一个杯子. 队列:先进先出  如同一个水管. import java.util.LinkedList; public cl ...

  4. C#控件及常用设计整

    C#控件及常用设计整 1.窗体    1 2.Label 控件    3 3.TextBox 控件    4 4.RichTextBox控件    5 5.NumericUpDown 控件    7 ...

  5. 介绍开源的.net通信框架NetworkComms框架 源码分析(十九 )ConnectionIncomingData

    原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是 ...

  6. Android Volley框架的使用(2)

    3. 设置请求类型和参数 Volley默认的请求类型是GET,如果需要用POST,可以在构造函数中进行设置.设置参数可以通过重写getParams()方法来实现. private void postR ...

  7. Android获取ROOT权限

    获取Android的ROOT权限其实很简单,只要在Runtime下执行命令"su"就可以了. // 获取ROOT权限 public void get_root(){ if (is_ ...

  8. MySQL: @variable vs. variable. Whats the difference?

    MySQL: @variable vs. variable. Whats the difference?   up vote351down votefavorite 121 In another qu ...

  9. Delphi String 常用字串符处理函数

    Delphi 在面对跨平台开发,程序语言也改进不少,不过有些改进,让原本 Delphi 开发者有些不适应,最显注的就是字串处理函数了,原本 Pascal 语言字串起始由 1 开始,几乎是它的经典了,新 ...

  10. 由一个异常开始思考springmvc参数解析

    首先记录一下异常,以及异常出现的原因和解决方案 异常主要信息: -- ::, ERROR [.jsp] - Name for argument type [java.lang.String] not ...