熟练使用KVC 可以再开发过程中可以给我们带来巨大的好处,尤其是在json 转模型的时候,KVC让程序员摆脱了繁琐无营养的代码堆积。减少代码量就是减少出错的概率。KVC 用起来很灵活,这种灵活的基础是严格的命名要求。这种命名要求其实是一种约定。再程序的世界里,约定的作用远远大于开发本身,良好的约定可以使程序员摆脱很多判断,也减少了错误。KVC有如下几点作用:

1)、直接赋值

使用KVC 可以对对象的某个属性进行赋值。假定现在我们有一个Person 类,类中包含两个属性:一个是只读的name 属性,一个是Number类型的age属性。

  1. //
  2. // Person.h
  3. // KVC
  4. //
  5. // Created by 邓竹立 on 15-4-24.
  6. // Copyright (c) 2015年 GiveMeFive. All rights reserved.
  7. //
  8.  
  9. #import <Foundation/Foundation.h>
  10.  
  11. @interface Person : NSObject
  12.  
  13. @property(nonatomic,copy,readonly)NSString* name;
  14.  
  15. @property(nonatomic,assign)NSNumber *age;
  16.  
  17. @end

当我们定义了属性的时候,系统就为我们自动的生成了setter 和getter 方法。我们可以通过setter 和getter方法,或读取或写入数值。当然我们也可以用KVC 的方式进行读写数据。先看一下代码,然后我们再简述一下需要注意的问题。

  1. #import "ViewController.h"
  2. #import "Person.h"
  3.  
  4. @interface ViewController ()
  5.  
  6. @end
  7.  
  8. @implementation ViewController
  9.  
  10. - (void)viewDidLoad
  11. {
  12. [super viewDidLoad];
  13.  
  14. Person *person=[[Person alloc] init];
  15.  
  16. [person setValue:@"" forKey:@"age"];
  17. [person setValue:@"皮拉夫大王" forKey:@"name"];
  18.  
  19. NSLog(@"person 的名字是%@",person.name);
  20. NSLog(@"person 的年领是%@",[person valueForKey:@"age"]);
  21. }
  22.  
  23. @end

2015-04-24 20:40:13.286 KVC[6208:218095] person 的名字是皮拉夫大王

2015-04-24 20:40:13.287 KVC[6208:218095] person 的年领是25

如果你没有接触过KVC 的话,你大概会想:我擦,大王的脑子坏掉了吧?只读的属性怎么可以赋值?!还有age属性明明是NSNumber类型的,怎么可以把字符串赋给它?!没错,这就是我想说的,KVC 不但能够赋值,而且还能破坏只读的特性。当然这只是我们需要注意的一个细节,更重要的是KVC 有自动装箱(自动类型转换)的功能,我们不需要去转换类型了。由于开发过程中数据领域是字符串的天下,所以这个自动装箱的功能的确是极好的。

2)、支持键值路径

什么叫支持键值路径?说白了就是支持嵌套。假如现在有一个书籍类,类中包含了书籍的名称name。书籍可以被Person所拥有(就是可以作为person的属性)

  1. #import <Foundation/Foundation.h>
  2.  
  3. @interface Book : NSObject
  4.  
  5. @property(nonatomic,copy)NSString* name;
  6.  
  7. @end

那么我们就可以这样来用

  1. Person *person=[[Person alloc] init];
  2. Book *myBook=[[Book alloc] init];
  3. person.book=myBook;
  4.  
  5. [person setValue:@"程序员摊煎饼指南" forKeyPath:@"book.name"];
  6.  
  7. NSLog(@"%@",[person valueForKeyPath:@"book.name"]);

这里的key直接使用点局分开就好了,注意一下:这里使用的时keyPath,当然在   “ 1)属性赋值”   中我们也可以使用keyPath,只不过再不必要的情况下使用keyPath会浪费性能而已。这里没啥可说的了,说多了都对不起我一度5毛的电费。

3)支持操作符

假如我们有10个字符串,我们想求出这10个字符串的总长度,我们可以使用KVC提供的操作符。

  1. NSArray *books=@[@"鸟哥烧烤私房菜",@"程序员摊煎饼宝典",@"麻辣烫基础教程"];
  2. NSLog(@"%@",[books valueForKeyPath:@"@sum.length"]);

这里的@sum 是KVC 提供的,不是我们写的。像这样的函数共有5个@avg,@count,@max,@min,@sum。我们直接用就可以了。但是据说效率比用for循环慢。我没有测试过,感兴趣的话你可以测试一下。

4)错误拦截

对于我们前端程序员来说,后端程序员有时也是一个troubleMaker。他总是给你传递一些很奇怪的东西。比如给你传递一个id 属性,或者什么都不给你传。如果有这样一个json文件 {“id”:"1"}。这是逼着我们把id作为数据模型的一个属性的节奏啊!!老夫不愿意啊!尽管作为属性也不会报错。屈服?还是抗争?这是一个问题。但是好在前辈们已经给了我们答案。假如我们有一个Model类,类中的whoCare属性就是本应命名为id 的属性。我们还写了一个字典转模型的初始化方法。

  1. @interface Model : NSObject
  2.  
  3. @property(nonatomic,strong)id whoCare;
  4.  
  5. -(instancetype)initWithDict:(NSDictionary *)dict;
  6.  
  7. @end

那么我们可以在.m文件中重写 -(void)setValue:(id)value forUndefinedKey:(NSString *)key 方法。这个方法会在字典转模型时,系统找不到同名的属性时调用。所以我们可以再这个方法中进行错误拦截,并进行赋值操作,这样就不会报错了。

  1. #import "Model.h"
  2.  
  3. @implementation Model
  4.  
  5. -(instancetype)initWithDict:(NSDictionary *)dict
  6. {
  7. if (self=[super init])
  8. {
  9. //忘了介绍了 字典转模型的常用语句
  10. [self setValuesForKeysWithDictionary:dict];
  11. }
  12. return self;
  13. }
  14.  
  15. -(void)setValue:(id)value forUndefinedKey:(NSString *)key
  16. {
  17. if ([key isEqualToString:@"id"])
  18. {
  19. self.whoCare=value;
  20. }
  21. }
  22.  
  23. @end

写好了模型类,我们可以来测试一下。

  1. #import "Model.h"
  2.  
  3. @interface ViewController ()
  4.  
  5. @end
  6.  
  7. @implementation ViewController
  8.  
  9. - (void)viewDidLoad
  10. {
  11. [super viewDidLoad];
  12. NSDictionary *dict=@{@"id":@""};
  13.  
  14. Model *model=[[Model alloc] initWithDict:dict];
  15.  
  16. NSLog(@"%@",model.whoCare);
  17. }
  18.  
  19. @end

程序没有崩溃,而且赋值成功。不信你看打印信息

2015-04-24 21:12:00.676 KVC[6393:228807] 1

 

 

IOS 高级开发 KVC(一)的更多相关文章

  1. IOS 高级开发 KVC(二)

    前一篇博客最后介绍了KVC 再json 转模型时遇到一些问题.今天接着来介绍KVC 的其他用法.其实我们在一开始的时候就一直再强调命名的重要性.命名规范是KVC 存活的基础.如果没有这个条件支撑,那么 ...

  2. (转发)IOS高级开发~Runtime(四)

    用C代替OC: #import <objc/runtime.h> #import <objc/message.h> #import <stdio.h> extern ...

  3. (转发)IOS高级开发~Runtime(三)

    11.系统类的方法实现部分替换 - (void) methodExchange { Method m1 = class_getInstanceMethod([NSStringclass],@selec ...

  4. (转发)IOS高级开发~Runtime(二)

    一些公用类: @interface ClassCustomClass :NSObject{ NSString *varTest1; NSString *varTest2; NSString *varT ...

  5. (转发)IOS高级开发~Runtime(一)

    IOS高级开发-Runtime(一) IOS高级开发-Runtime(二) IOS高级开发-Runtime(三) IOS高级开发-Runtime(四) 一些公用类: @interface Custom ...

  6. IOS高级开发之多线程(四)NSOperation

    1.什么是NSOperation,NSOperationQueue? NSOperation是一个抽象的基类,表示一个独立的计算单元,可以为子类提供有用且线程安全的建立状态,优先级,依赖和取消等操作. ...

  7. IOS高级开发 runtime(一)

    一. 简介 IOS 开发中灵活使用runtime 会提高我们的程序性能和开发速度.要想使用runtime,首先要引入系统的头文件. <span style="font-size:18p ...

  8. BAT面试经验分享——iOS高级开发工程师的自我总结!

    序言 目前形势,参加到iOS队伍的人是越来越多,甚至已经到供过于求了. 今年,找过工作人可能会更深刻地体会到今年的就业形势不容乐观,随着各大公司秋招的开始,很多小伙伴都行动起来了,我也有幸获得了一份不 ...

  9. ios高级开发之多线程(三)GCD技术

    GCD是基于C的API,它是libdispatch的的市场名称.而libdispatch作为Apple公司的一个库,为并发代码在多核硬件(跑IOS或者OS X)上执行提供有力支持. 那么我们为什么要用 ...

随机推荐

  1. java类的访问控制符与其他几个特殊修饰符的总结

    1  访问控制符 1.1 字段或者方法的访问控制符   同一个类中 同一个包中 不同包中的子类 不同包中的非子类 private YES       默认(包可访问) YES YES     prot ...

  2. SQLite使用教程4 附加数据库

    http://www.runoob.com/sqlite/sqlite-attach-database.html SQLite 附加数据库 假设这样一种情况,当在同一时间有多个数据库可用,您想使用其中 ...

  3. 我的AndroidStudio设置

    转载:http://stormzhang.com/devtools/2014/11/25/android-studio-tutorial1/ 官方下载有两个地方,均需要FQ. Android Deve ...

  4. js url传值中文乱码之解决之道

    在websphere 中使用的是url=encodeURI(encodeURI(url)); //用了2次encodeURI 测试成功,第一次转换没有尝试, 处理方法一. js 程序代码:url=en ...

  5. svn项目导入

    svn项目导入 在已建立好svnserverserver的情况下.且所用电脑上已装好svn,在电脑上导入svn项目 首先,新建目录.点击鼠标右键,选择TortoiseSVN–>export 然后 ...

  6. LVS NAT模型

    1,环境 VMWare10, CentOS6.3 2,LVS NAT网络规划 可以看到Director机器有2个IP,也就是说需要2张网卡:Real Server只需要一个网卡. VIP: 虚拟IP, ...

  7. MyDetailedOS

    http://njumdl.sinaapp.com/ https://github.com/mudongliang

  8. careercup-中等难度 17.8

    17.8 给定一个整数数组(有正数和负数),找出总和最大的连续序列,并返回总和. 解法: 就是求连续子序列的和最大,不过存在一个问题: 假设整个数组都是负数,怎么样才是正确的行为呢?看看这个简单的数组 ...

  9. 文件和目录之chmod和fchmod函数

    本篇博文内容摘自<UNIX环境高级编程>(第二版),仅作个人学习记录所用.关于本书可参考:http://www.apuebook.com/. 这两个函数使我们可以更改现有文件的访问权限: ...

  10. android离线安装adt

    打开Eclipse, 在菜单栏上选择help->Install New SoftWare 出现如下界面: 点击 Add按钮,出现如下界面 在Name这而随意输入一个名字:ADT15:点击打开Ar ...