本章将分为三个部分:

  • KVC是什么
  • KVC之Set/Get
  • KVC键值路径之Set/Get

KVC是什么

KVC,即 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性,并不需要调用setter/getter函数或者类的实例变量。

KVC之Set/Get

类A中有3个变量,都是private权限,关于访问权限的,请参见《Objective-C 成员变量

A.h

@interface A : NSObject
{
@private
NSString *str;
NSInteger value;  //注意这里没星号哦哦哦
NSArray *array;
}
@end

A.m:重写Description函数,用于NSLog

@implementation A
/**
* 重写Description方法,可用于NSLog打印
*/
- (NSString *)description
{
return [NSString stringWithFormat:@"\n%@\n%li\n%@", str, (long)value, array];
}
@end

Main.m:理论上来说,外部变量是访问不到这3个私有变量的,但是暴力的KVC来了。

A *a = [[A alloc] init];

//KVC之set
[a setValue:@"HelloWorld" forKey:@"str"];
[a setValue:@ forKey:@"value"];
[a setValue:@[@"HearthStone", @] forKey:@"array"]; NSLog(@"%@", a); //KVC之get
NSString *str = [a valueForKey:@"str"];
NSInteger value = [[a valueForKey:@"value"] integerValue]; //id 转为 NSInteger
NSArray *array = [a valueForKey:@"array"]; NSLog(@"\n%@\n%ld\n%@", str, (long)value, array);

输出为

HelloWorld
2015
(
HearthStone,
2
)

HelloWorld
2015
(
HearthStone,
2
)

分析:

KVC的Set方法(重点)

[a setValue:@"HelloWorld" forKey:@"str"];

是KVC的set方法,其中key一定要为消息接收者的属性名称,而不能是自定义的。

KVC的Get方法(重点)

NSString *str = [a valueForKey:@"str"];

是KVC的get方法,其中key一定要为消息接收者的属性名称,而不能是自定义的。

当Set方法遇到基本数据类型

[a setValue:@ forKey:@"value"];

NSInteger是基本数据类型,设置基本数据类型的时候,需要将基本类型转化成NSNumber,在设置值的时候,系统会有自动解包的过程,NSNumber会解包赋值给value.

当Get方法遇到基本数据类型

NSInteger value = [[a valueForKey:@"value"] integerValue];  //id 转为 NSInteger

valueForKey返回的是id类型,id转换为NSInteger的方法应该是上面这种,而下面这种写法是错误的!

NSInteger value = (NSInteger)[a valueForKey:@"value"];

题外话:重写Description来方便NSLog的输出

- (NSString *)description
{
return [NSString stringWithFormat:@"\n%@\n%li\n%@", str, (long)value, array];
} NSLog(@"%@", a);

将打印出

HelloWorld
2015
(
HearthStone,
2
)

KVC键值路径之Set/Get

假如A含有一个类B,那么如何通过KVC拿到B的属性呢?答案是使用键值路径。

A.h

@interface A : NSObject
{
@private
NSString *str;
NSInteger value;  //注意这里没星号哦哦哦
NSArray *array;
B *b;
}
@end

B.h

@interface B : NSObject
{
@private
NSinteger *age;
}
@end

现在,假如A的array里面装的都是B(装B--)

Main.m

A *a = [[A alloc] init];
...//set Object
[a setValue:@ forKeyPath:@"b.age"]; NSArray *array = [a valueForKeyPath:@"array.age"]; //返回了数组中所有B的age
NSInteger count = [a valueForKeyPath:@"array.@count"]; //返回了数组中B的个数
NSInteger maxAge = [a valueForKeyPath:@"array.@max.age"]; //返回了数组中B的age最大的
NSInteger sumAge = [a valueForKeyPath:@"array.@sum.age"]; //返回了数组中B的age和
NSInteger avgAge = [a valueForKeyPath:@"array.@avg.age"]; //返回了数组中B的age平均值

键值路径可以用来访问不是基本类型的实例变量的属性,也可以快速取到数组中的对象的同一个属性,同时可以利用@count @max @sum @avg等进行计算。

KVC的键值路径的Set方法(重点)

[a setValue:@ forKeyPath:@"b.age"];

KVC的键值路径的Get方法(重点)

NSArray *array = [a valueForKeyPath:@"array.age"];        //返回了数组中所有B的age

KVC/KVO之暴力的KVC的更多相关文章

  1. KVC & KVO

    KVC和KVO看上去又是两个挺牛的单词简写,KVC是Key-Value Coding的简写,是键值编码的意思.KVO是Key-Value  Observing的简写,是键值观察的意思.那么我们能拿KV ...

  2. KVC/KVO原理详解及编程指南

    一.简介 1.KVC简介 2.KVO简介 二.KVC相关技术 1.Key和Key Path 2.点语法和KVC 3.一对多关系(To-Many)中的集合访问器方法 4.键值验证(Key-Value V ...

  3. 深入理解 KVC\KVO 实现机制 — KVC

    KVC和KVO都属于键值编程而且底层实现机制都是isa-swizzing,所以本来想放在一起讲的.但是篇幅有限所以就分成了两篇博文 KVO实现机制传送门 KVC概述 KVC是Key Value Cod ...

  4. kvc kvo(摘录)

    概述 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby.Python的动态特性,例如动态类型.动态加载.动态绑定等.今天我们着重介绍ObjC中的键值编码(KVC).键值监听( ...

  5. 【转】 KVC/KVO原理详解及编程指南

    原文地址:http://blog.csdn.net/wzzvictory/article/details/9674431 前言: 1.本文基本不讲KVC/KVO的用法,只结合网上的资料说说对这种技术的 ...

  6. kvc/kvo复习

    kvc/kvo复习 1 小问题 '[<XMGPerson 0x7fb8a8f30220> setValue:forUndefinedKey:]: this XMGPerson * pers ...

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

      作者:wangzz 原文地址:http://blog.csdn.net/wzzvictory/article/details/9674431 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或 ...

  8. 阶段性总结⓵触摸事件&手势识别⓶Quartz2D绘图⓷CALayer图层⓸CAAnimation⓹UIDynamic UI动力学⓺KVC&KVO

    知识点复习   1. 触摸事件&手势识别   1> 4个触摸事件,针对视图的 2> 6个手势识别(除了用代码添加,也可以用Storyboard添加)   附加在某一个特定视图上的, ...

  9. IOS开发之KVC KVO KVB

    KVC(Key Value Coding) KVO(Key Value Observing) KVB(Key Value Binding) KVO是Cocoa的一个重要机制,他提供了观察某一属性变化的 ...

随机推荐

  1. 揭秘ThreadLocal(转)

    转载自:掘金大闲人柴毛毛博客. ThreadLocal是开发中最常用的技术之一,也是面试重要的考点.本文将由浅入深,介绍ThreadLocal的使用方式.实现原理.内存泄漏问题以及使用场景. Thre ...

  2. Appium安装过程

    Appium安装过程 先安装了 Node.js.在node的官网上下载的exe安装文件. 在node的command line中执行 npm install -g appium 来安装appium,报 ...

  3. javascript 模块化模式总结(二)

    一.对象字面值 这种设计模式中,一个对象被描述为一组以逗号分隔的名称/值对括在大括号({})的集合.对象内部的名称可以是字符串或是标记符后跟着一个冒号":".在对象里最后一个名称/ ...

  4. xUtils中用DbUtils,ViewUtils的用法

    一.有关xUtils的简介 xUtils 包含了很多实用的android工具.xUtils 最初源于Afinal框架,进行了大量重构,使得xUtils支持大文件上传,更全面的http请求协议支持(10 ...

  5. 自己动手写CPU之第四阶段(3)——MIPS编译环境的建立

    将陆续上传本人写的新书<自己动手写CPU>(尚未出版).今天是第13篇.我尽量每周四篇 4.4 MIPS编译环境的建立 OpenMIPS处理器在设计的时候就计划与MIPS32指令集架构兼容 ...

  6. 发布WebService 1.1

    webservice1.1是基于jdk发布的 package cn.itcast.service01; import javax.jws.WebService; import javax.xml.ws ...

  7. sqlserver学习笔记(六)—— sqlserver内置函数(字符串、日期)

    sqlserver中有很多内置函数,这里总结了一些常用的 一.关于字符串的函数: 1.CHARINDEX 寻找一个指定字符串在另一个字符串中的起始位置 SELECT CHARINDEX('world‘ ...

  8. 摘:"error LNK2019: 无法解析的外部符号 该符号在函数 中被引用" 错误原因

    例如“error LNK2019: 无法解析的外部符号error LNK2001: 无法解析的外部符号“private: static struct _OVERLAPPED CUsbCom::g_Wr ...

  9. python 多线程 示例

    import threading import Queue q = Queue.Queue() from test import * def worker1(x, y): #假设耗时 执行完毕 大于三 ...

  10. unity, 鼠标与场景交点

    在鼠标与场景交点上放一个mark,并于1s后消失: 新建一个空GameObject,命名为moushHitTest,添加下面脚本: using UnityEngine;using System.Col ...