IOS 高级开发 KVC(二)
前一篇博客最后介绍了KVC 再json 转模型时遇到一些问题。今天接着来介绍KVC 的其他用法。其实我们在一开始的时候就一直再强调命名的重要性。命名规范是KVC 存活的基础。如果没有这个条件支撑,那么KVC使用起来就不会那么简单了。在这里大王再哔哔几句,作为一个程序员,不管我们长得有多丑,我们的代码一定好看。一段规范的代码代表我们的脸面,也是程序员成熟的标志。既然说到了命名,那么就再来看看KVC 让人吃惊的一面。
1)KVC 方法的搜索顺序
当你看到这个标题的时候,可能会诧异,说的是啥啊?啥是搜索顺序啊?别着急,在介绍调用顺序之前,我们先来看一段很简单的代码,先热身一下。假设我们有一个Person类,这个类是个宅男,头文件中啥玩意都没有。既然头文件中没有任何属性,我们就直接看实现文件。
#import "Person.h" @interface Person () @property(nonatomic,copy)NSString* yourHand; @end @implementation Person -(instancetype)init
{
self=[super init];
if (self)
{
self.yourHand=@"你的右手";
}
return self;
} -(NSString*)girlFriend
{
NSLog(@"%s",__func__);
return self.yourHand;
} @end
为了防止宅男太过孤单,作为上帝的我,给他创建了手,并在一出生(init)时就给它赋值了。并且创建了一个girlFriend方法。如果我们想调用这个方法直接
[person girlFriend]是不行的(但是我们可以[person performSleector:@selector(girlFriend)],这是因为runtime的关系,这里不详细介绍,可以参看我前几篇博客),在这里,我们还可以这样调用
- (void)viewDidLoad
{
[super viewDidLoad]; Person *person=[[Person alloc] init]; NSLog(@"%@",[person valueForKey:@"girlFriend"]);
}
2015-04-27 20:56:37.207 KVC[19591:953199] -[Person girlFriend]
2015-04-27 20:56:37.207 KVC[19591:953199] 你的右手
了解了上面的内容,我们就可以来说说KVC与容器类。什么是容器类呢?说简单点就是数组和集合。这里没啥可说的,还是先看代码吧。还是这个Person类,我们先来稍微改动一下。头文件还是什么都没有,实现文件变为如下
#import "Person.h" @implementation Person -(NSUInteger)countOfFingers
{
return ;
} -(id)objectInFingersAtIndex:(NSUInteger)index
{
NSLog(@"这是第%lu个手指",index);
return @(index);
} @end
光看这段代码不神奇,再看一下测试方法和打印信息,我们就会感到很吃惊。
- (void)viewDidLoad
{
[super viewDidLoad]; Person *person=[[Person alloc] init]; NSLog(@"%@",[person valueForKey:@"fingers"]);
}
2015-04-27 21:10:53.990 KVC[19658:958083] 这是第0个手指
2015-04-27 21:10:53.991 KVC[19658:958083] 这是第1个手指
2015-04-27 21:10:53.991 KVC[19658:958083] 这是第2个手指
2015-04-27 21:10:53.991 KVC[19658:958083] 这是第3个手指
2015-04-27 21:10:53.991 KVC[19658:958083] 这是第4个手指
2015-04-27 21:10:53.991 KVC[19658:958083] 这是第5个手指
2015-04-27 21:10:53.991 KVC[19658:958083] 这是第6个手指
2015-04-27 21:10:53.992 KVC[19658:958083] 这是第7个手指
2015-04-27 21:10:53.992 KVC[19658:958083] 这是第8个手指
2015-04-27 21:10:53.992 KVC[19658:958083] 这是第9个手指
2015-04-27 21:10:53.992 KVC[19658:958083] (
0,
1,
2,
3,
4,
5,
6,
7,
8,
9
)
全过程我们都没有直接调用countOfFingers 和-(id)objectInFingersAtIndex:(NSUInteger)index 方法。由打印信息可以知道是系统帮我们调用了。并且有打印信息我们可以知道,系统把fingers 当成属性,并且这个“属性”是数组类型的。当我们调用valueForKey:时,系统会按如下顺序调用方法
如果都找不到的话,系统会调用valueForUndefinedKey:方法。以上所讲的都是针对不可变的容器类。如果是可变的容器类,我们可以可以这样使用
dataM= [data mutbaleArrayValueForKey:@"属性"]。当dataM改变的时候,会向data发送消息,data中的内容也会跟着改变。这里我就不详细演示了,有兴趣的可以自己试一下。
2)高阶消息传递
大家可能冷不丁的看到高阶这个词感觉很高大上,仿佛又回到了大学的高数课堂。那么什么是高阶消息传递呢?说白了就是让数组中的每一个元素都执行某个方法,并把结果返回到新的数组中。这下感觉不那么高大上了吧?下面来看一个经典的例子代码
- (void)viewDidLoad
{
[super viewDidLoad]; NSArray *array=@[@"烤串",@"啤酒",@"爆米花"];
NSArray *lengths=[array valueForKeyPath:@"capitalizedString.length"];
NSLog(@"%@",lengths);
}
2015-04-27 21:53:25.531 KVC[19821:972219] (
2,
2,
3
)
我们可以看出,数组中的每一项都执行了capitalizedString 方法,执行完后,又执行了length 方法。然后把结果返回到新的数组中。在开发中,我们可以适当的使用这个方法,会减少我们的代码量。
尽管KVC很高大上,但是我们现实开发中,还是谨慎地使用,因为它太过于强大,贸然使用可能会无意间破坏程序的封装性。所以我们只有想清楚了之后再使用,而且最好在使用的地方加上注释。KVC 是大招,我们要在必要的时候使用,动画片里孙悟空也不是在一开始就放大招,你说是不?
IOS 高级开发 KVC(二)的更多相关文章
- IOS 高级开发 KVC(一)
熟练使用KVC 可以再开发过程中可以给我们带来巨大的好处,尤其是在json 转模型的时候,KVC让程序员摆脱了繁琐无营养的代码堆积.减少代码量就是减少出错的概率.KVC 用起来很灵活,这种灵活的基础是 ...
- (转发)IOS高级开发~Runtime(二)
一些公用类: @interface ClassCustomClass :NSObject{ NSString *varTest1; NSString *varTest2; NSString *varT ...
- (转发)IOS高级开发~Runtime(四)
用C代替OC: #import <objc/runtime.h> #import <objc/message.h> #import <stdio.h> extern ...
- (转发)IOS高级开发~Runtime(三)
11.系统类的方法实现部分替换 - (void) methodExchange { Method m1 = class_getInstanceMethod([NSStringclass],@selec ...
- (转发)IOS高级开发~Runtime(一)
IOS高级开发-Runtime(一) IOS高级开发-Runtime(二) IOS高级开发-Runtime(三) IOS高级开发-Runtime(四) 一些公用类: @interface Custom ...
- iOS蓝牙开发(二)蓝牙相关基础知识
原文链接: http://liuyanwei.jumppo.com/2015/07/17/ios-BLE-1.html iOS蓝牙开发(一)蓝牙相关基础知识: 蓝牙常见名称和缩写 MFI ====== ...
- IOS高级开发之多线程(四)NSOperation
1.什么是NSOperation,NSOperationQueue? NSOperation是一个抽象的基类,表示一个独立的计算单元,可以为子类提供有用且线程安全的建立状态,优先级,依赖和取消等操作. ...
- IOS 高级开发 runtime(二)
二.移魂大法 使用runtime还可以交换两个函数.先贴上代码和执行结果. #import <Foundation/Foundation.h> @interface DZLPerson : ...
- ios高级开发之多线程(二)NSThread技术
多线程技术是有多套解决方案的,那么我们该如何选择呢? 技术方案 简介 语言 线程生命周期 使用频率 pthread 1.一套通用的多线程API 2.适用于UNIX,linux,windows等 3.跨 ...
随机推荐
- NGUI学习笔记(四):动态加载UI和NGUI事件
动态加载UI 我们进入一个场景后,如果将这个场景所有可能用到的UI都直接放在场景中做好,由于要在进入场景时就部署好所有的UI对象,那么当UI对象较多时会碰到的问题是:1.初始化场景会产生非常明显的卡顿 ...
- C++学习笔记(十五):异常
C++之父Bjarne Stroustrup在<The C++ Programming Language>中讲到:一个库的作者可以检测出发生了运行时错误,但一般不知道怎样去处理它们(因为和 ...
- MSSQLSERVER数据库- 配置数据库邮件配置的操作过程
还是第一次发现数据库可以发邮件.查了一下百度,试了一下,发现可以. 1.简单了解数据库邮件的概念和使用的传输协议及系统体系: 数据库邮件是从 SQL Server 数据库引擎中发送电子邮件的企业解决方 ...
- MSSQLSERVER数据库- SP_EXECUTESQL的使用
EXEC和SP_EXECUTESQL有什么区别呢? 1,它们之间最大的区别是嵌入式的参数,如下面一个语句 declare @sql nvarchar() declare @id varchar() ' ...
- CentOS 6.5 下载地址
CentOS 6.5 主要改动 Precision Time Protocol(精确时间协议)—— 原先是项技术预览 —— 现在已获全面支持.以下驱动程序支持网络时间戳印:bnx2x.tg3.e100 ...
- C# 设置 窗口最大化
Main.WindowState = FormWindowState.Maximized;
- android学习日记12--布局管理器
1.概述 布局管理器的用途: a.可以更好的管理组件; b.通过使用布局管理器,Android应用程序可以做到平台无关性 布局管理器都是ViewGroup的子类,所有可充当容器的父类都是ViewGro ...
- Golang-interface(四 反射)
github:https://github.com/ZhangzheBJUT/blog/blob/master/reflect.md 一 反射的规则 反射是程序执行时检查其所拥有的结构.尤其是类型的一 ...
- 文件和目录之stat、fstat和lstat函数
#include <sys/stat.h> int stat( const char *restrict pathname, struct stat *restrict buf ); in ...
- java_jdbc_反射技术将查询结果封装为对象
package cn.itcast.Reflect; import java.lang.reflect.InvocationTargetException; import java.lang.refl ...