IOS 高级开发 KVC(一)

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

1)、直接赋值

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

//
//  Person.h
//  KVC
//
//  Created by 邓竹立 on 15-4-24.
//  Copyright (c) 2015年 GiveMeFive. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property(nonatomic,copy,readonly)NSString* name;

@property(nonatomic,assign)NSNumber *age;

@end

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

#import "ViewController.h"
#import "Person.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    Person *person=[[Person alloc] init];

    [person setValue:@"25" forKey:@"age"];
    [person setValue:@"皮拉夫大王" forKey:@"name"];

    NSLog(@"person 的名字是%@",person.name);
    NSLog(@"person 的年领是%@",[person valueForKey:@"age"]);
}

@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的属性)

#import <Foundation/Foundation.h>

@interface Book : NSObject

@property(nonatomic,copy)NSString* name;

@end

那么我们就可以这样来用

    Person *person=[[Person alloc] init];
    Book *myBook=[[Book alloc] init];
    person.book=myBook;

    [person setValue:@"程序员摊煎饼指南" forKeyPath:@"book.name"];

    NSLog(@"%@",[person valueForKeyPath:@"book.name"]);

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

3)支持操作符

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

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

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

4)错误拦截

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

@interface Model : NSObject

@property(nonatomic,strong)id whoCare;

-(instancetype)initWithDict:(NSDictionary *)dict;

@end

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

#import "Model.h"

@implementation Model

-(instancetype)initWithDict:(NSDictionary *)dict
{
    if (self=[super init])
    {
        //忘了介绍了 字典转模型的常用语句
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

-(void)setValue:(id)value forUndefinedKey:(NSString *)key
{
    if ([key isEqualToString:@"id"])
    {
        self.whoCare=value;
    }
}

@end

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

#import "Model.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSDictionary *[email protected]{@"id":@"1"};

    Model *model=[[Model alloc] initWithDict:dict];

    NSLog(@"%@",model.whoCare);
}

@end

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

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

 

 

时间: 2024-08-19 20:38:05

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

IOS 高级开发 KVC(二)

前一篇博客最后介绍了KVC 再json 转模型时遇到一些问题.今天接着来介绍KVC 的其他用法.其实我们在一开始的时候就一直再强调命名的重要性.命名规范是KVC 存活的基础.如果没有这个条件支撑,那么KVC使用起来就不会那么简单了.在这里大王再哔哔几句,作为一个程序员,不管我们长得有多丑,我们的代码一定好看.一段规范的代码代表我们的脸面,也是程序员成熟的标志.既然说到了命名,那么就再来看看KVC 让人吃惊的一面. 1)KVC 方法的搜索顺序 当你看到这个标题的时候,可能会诧异,说的是啥啊?啥是搜

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

一些公用类: @interface ClassCustomClass :NSObject{ NSString *varTest1; NSString *varTest2; NSString *varTest3; } @property (nonatomic,assign)NSString *varTest1; @property (nonatomic,assign)NSString *varTest2; @property (nonatomic,assign)NSString *varTest3

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

11.系统类的方法实现部分替换 - (void) methodExchange { Method m1 = class_getInstanceMethod([NSStringclass],@selector(lowercaseString)); Method m2 = class_getInstanceMethod([NSStringclass],@selector(uppercaseString)); method_exchangeImplementations(m1, m2); NSLog(

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

用C代替OC: #import <objc/runtime.h> #import <objc/message.h> #import <stdio.h> extern int UIApplicationMain (int argc,char *argv[],void *principalClassName,void *delegateClassName); struct Rect { float x; float y; float width; float height;

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

IOS高级开发-Runtime(一) IOS高级开发-Runtime(二) IOS高级开发-Runtime(三) IOS高级开发-Runtime(四) 一些公用类: @interface CustomClass : NSObject - (void) fun1; @end @implementation CustomClass - (void) fun1 { NSLog(@"fun1"); } @end @interface TestClass : NSObject @end @imp

iOS高级开发——CollectionView的cell中按钮的点击实现

在我刚初学iOS的时候,我就问一些大神,iOS开发中最难的哪些部分.有些人就说是自定义控件.UI和交互设计.那个时候我将信将疑,随着自己开发的深入,自己的确是深有体会.开发一款App产品,很大一部分时间是在和UI打交道.因为开发中很多功能是直接封装好的或者有现成模板可以用的,唯有UI是根据不同的App千变万化的.所以今天我们继续来研究iOS中比较高级的控件--UICollectionView,来实现cell中按钮的点击操作.该demo我已经提交到: https://github.com/chen

iOS高级开发——CollectionView的cell长按事件实现

我们在使用TableView时,默认有单击或者侧滑删除等操作,但是原生的没有长按操作.而来到CollectionView中,又少了一个侧滑操作.在实际的项目开发中,我们需要使用单击或者长按来进行不同的操作,并获取cell的section和row.所以我们在CollectionView中来实现,在TableView中也是类似. 该demo我已经上传到  https://github.com/chenyufeng1991/CollectionView  .里面也包含了CollectionView的其

IOS高级开发 runtime(1)

一. 简介 IOS 开发中灵活使用runtime 会提高我们的程序性能和开发速度.要想使用runtime,首先要引入系统的头文件. #import <objc/runtime.h> 当我们查看runtime.h的时候,我们会发现,其实runtime是很有条理的 const char *object_getClassName(id obj) //获取对象的类 Ivar *class_copyIvarList(Class cls, unsigned int *outCount) //获取类的变量列

《转载》IOS高级开发~开机启动&amp;无限后台运行&amp;监听进程

非越狱情况下实现: 开机启动:App安装到IOS设备设备之后,无论App是否开启过,只要IOS设备重启,App就会随之启动: 无限后台运行:应用进入后台状态,可以无限后台运行,不被系统kill: 监听进程:可获IOS设备运行除系统外的App(包括正在运行和后台运行): 配置项目 plist文件 添加: <key>UIBackgroundModes</key> <array> <string>voip</string> </array>