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.跨 ...
随机推荐
- 浅析作用域链–JS基础核心之一
JS中的作用域,大家都知道的,分为全局作用域和局部作用域,没有块级作用域,听起来其实很简单的,可是作用域是否能够有深入的了解,对于JS代码逻辑的编写成功率,BUG的解决能力,以及是否能写出更优秀的代码 ...
- 提高你的Java代码质量吧:少用静态导入
一.分析 从Java 5开始引入静态导入语法(import static),其目的是为了减少字符输入量,提高代码的可阅读性,以便更好地理解程序. 但是,滥用静态导入会使程序更难阅读,更难维护.静态导 ...
- 经常使用的webservice接口
Web Service 一些对外公开的网络服务接口 2011-10-29 14:12 商业和贸易: 1.股票行情数据 WEB 服务(支持香港.深圳.上海基金.债券和股票:支持多股票同一时候查询) En ...
- 【转】通过CMD命令设置定时关机及ShutDown命令大全
经常会遇到这种情况:现在有个事情要离开很长时间,到那还在下载一个东西仅差10分钟就完成了,或者杀毒之类,不想让电脑一直开着也不想现在就停止工作.这是就会用到定时关机. 电脑系统设置(CMD命令)智能关 ...
- iOS 10 升级后无法真机测试 Could not find Developer Disk Image
---2016年9月20日更新 iOS 升级到10之后,你会发现无法进行真机测试了.这种情况我在iOS 8.4 .9.3更新的时候也遇到过.原因是Xcode 的DeviceSupport里面缺少了iO ...
- 跟我学solr---吐槽一下,我的文章被抄袭啦
今天闲来无事,就在在百度上搜了下面"跟我学solr",看看这几周来自己的努力成果怎么样,不搜还好,搜了就图学了.被原封不动地抄袭了!并且抄袭的文章还在百度排名第一,我自己的却被排到 ...
- Java ServletContext 详解
ServletContext, 是一个全局的储存信息的 空间,服务器开始,其就存在,服务器关闭,其才释放.request,一个用户可有多个:session,一个用户一个:而 servletContex ...
- Array.prototype.slice.call(arguments) 类数组转成真正的数组
Array.prototype.slice.call(arguments) 我们知道,Array.prototype.slice.call(arguments)能将具有length属性的对象转成数 ...
- 网页js生成当前年月日 星期
只需将下面代码插入需要显示日期的地方即可 <div style="color: brown; font-size: 10px;">今天是: <script lan ...
- 为什么虚拟机上刚装的centos7只有lo回环网络接口?
centos7默认安装时需要手动激活有线网卡.如果安装时没有激活,需要手动编辑vi /etc/sysconfig/network-scripts/下ifcfg-enoxxONBOOT="ye ...