`
444878909
  • 浏览: 639729 次
文章分类
社区版块
存档分类
最新评论

ios开发之你真的了解了KVC吗?

 
阅读更多

之前一直以为自己了解KVC 其实只是井底之蛙啦,真正的要把KVC原原本本的说出来还真的不是一件简单的事情。于是今天写下这边文章,告诫自己要知其然还要知其所以然。

一.KVC的基本概念

Key-value coding,它是一种使用字符串标识符,间接访问对象属性的机制,而不是直接调用getter 和 setter方法。通常我们使用valueForKey 来替代getter 方法,setValue:forKey来代替setter方法。

下面是使用KVC 和 不使用 KVC的代码对比

Persion *persion =  [ [Persion alloc] init ];

//不使用KVC
persion.name = @"hufeng" ;

//使用KVC的写法
[persion  setValue:@"hufeng" forKey:@"name"];

看出区别来了吗?你可能会说 你写的太简单了,我们实际用的时候不可能有这样复杂的类,下面我们写个复杂点的:我们有一个人 这个人有一个手机类 这个手机类 有一个电池类 我们要获取这个电池类 比之前复杂了吧。

没有KVC

Persion *persion =  [ [Persion alloc] init ];

Phone *phone = persion.phone;

Battery *battery = phone.battery;

使用KVC

Battery *battery = [persion valueForKeyPath: @"phone.battery" ];

注意- valueForKeyPath 里面的值是区分大小写的,你如果写出Phone.Battery 是不行的

说到这里你可能会问 我能不能对 NSArray 调用KVC吗? 答案是否定的,因为array 没有keys啊,但是你可以对array里面的item 使用KVC。

KVC 最常用的还是在序列化和反序列话对象。我们经常需要把json字符串反序列化成我们想要的对象 下面是一个例子 将字典用NSKeyedArchiver 序列化成对象

- (id)initWithDictionary:(NSDictionary *)dictionary {

    self = [self init];

    if (self){

        [self setValuesForKeysWithDictionary:dictionary];

    }

    return self;

}

注意 这里有一个坑 当我们setValue 给一个没有定义的字典值(forUndefinedKey)时 会抛出NSUndefinedKeyException异常的 记的处理此种情况

还有一个需要注意的是KVC 并没有类型检验,毕竟Object-C 还是动态的啦。 还是看下面的代码吧

[persion setValue:[NSNumber numberWithInteger:1] forKey:@"name"]; 
// compiles and runs

persion.name = [NSNumber numberWithInteger:1]; 
// won't compile: Incompatible pointer types assigning to 'NSString *' from 'NSNumber *'

setValue forKey 得到的对象是泛型的id, 只有在使用的时候才能确定类型。你可能会问不至于吧 OC 这样弱啊,当然不是 OC 提供了了一个方法validateValue来解决这个问题

@property (nonatomic, strong) NSString name;

- (BOOL)validateName:(id*)ioValue error:(NSError**)error {
    // Validation logic goes here

}

Person *p = [Person new];

NSString *name = @"Jason Hu";

NSError *error = nil;


// This call below actually calls our validateName: error: method

if ([p validateValue:&name forKey:@"name" error:&error]) {

    [p setValue:name forKey:@"name"];
}

你可能会问写这样多代码 才只验证了一个属性 那如果我这个类有n+个属性 难道我要写n+个验证方法吗?


二.KVC 验证

到这里我们对KVC已经有了一个初步印象,到这里其实还只是冰山一角。
下面我们要提高更高的要求,如果让key 支持 不区分大小写

下面我们提到一个方法initialize

initialize是在类或者其子类的第一个方法被调用前调用。所以如果类没有被引用进项目或者类文件被引用进来,但是没有使用,那么initialize也不会被调用 ,到这里 知道我们接下来要干嘛了吧

+ (void)initialize {
    [super initialize];

    dispatch_once(&onceToken, ^{
        modelProperties = [NSMutableDictionary dictionary];
        propertyTypesArray = @[/* removed for brevity */];
    });
    NSMutableDictionary *translateNameDict = [NSMutableDictionary dictionary];
    [self hydrateModelProperties:[self class] translateDictionary:translateNameDict];
    [modelProperties setObject:translateNameDict forKey:[self calculateClassName]];
}

+ (void)hydrateModelProperties:(Class)class translateDictionary:(NSMutableDictionary *)translateDictionary {
    if (!class || class == [NSObject class]){
        return;
    }

    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(class, &outCount);
    for (i = 0; i < outCount; i++){
        objc_property_t p = properties[i];
        const char *name = property_getName(p);
        NSString *nsName = [[NSString alloc] initWithCString:name encoding:NSUTF8StringEncoding];
        NSString *lowerCaseName = [nsName lowercaseString];
        [translateDictionary setObject:nsName forKey:lowerCaseName];
        //注意此处哦
        NSString *propertyType = [self getPropertyType:p];
        [self addValidatorForProperty:nsName type:propertyType];
    }
    free(properties);

    [self hydrateModelProperties:class_getSuperclass(class) translateDictionary:translateDictionary];
}

分享到:
评论

相关推荐

    IOS KVC和KVO

    已经拥有一年经验的你真的了解KVC,KVO吗?也许不!以前我以为自己都有上架项目,这都是太基础的东西,但今天我重新回头看了以前做的笔记,真的是书读百遍,其义自见。

    iOS KVC实现原理

    iOS KVC实现原理,供参考学习。适合有一定基础的。自己研究的,不喜勿喷。

    iOS KVC设计模式

    KVC(Key-Value Coding)是Objective-C中最强大最实用的功能之一。 通过例子可以帮你更好的理解它们。

    IOS KVC的一些简单用法

    使用kvc 可以轻松获取一个类的成员变量的值,也可以轻松获取数组中成员变量的zhi,

    KVC技术指南 ---ios官方

    KVC技术指南 ---ios官方

    iOS KVC实例

    键值编码允许开发者通过名字访问对象属性,而无需调用明确的存取方法。这是一个非常简单的例子,适合新手下载学习。

    ios 数据请求框架 图片请求框架 刷新框架 kvc框架,进度条框架

    ios 数据请求框架 图片请求框架 刷新框架 kvc框架,进度条框架

    IOS中KVC和KVO用法demo

    使用KVC对属性赋值 使用KVC对属性取值 KVC对数组取值 KVO是key value observing, 它是一种非常重要的机制,允许监听属性值的变化

    关于iOS获取属性你真的了解吗?

    属性对各位iOS开发者来说应该都不陌生,如果iOS中谈到取属性,相信大家都会夸夸其谈,不就是get方法吗?或者大谈kvc取属性的机制。不得不说这些也是对的。这时大家可能就疑惑了,那你还要说啥的!!大家不妨想想,...

    KVC_KVOTest Demo代码

    KVC_KVOTest Demo代码 KVC KVO IOS 观察者 Observe

    oc中的通知,kvc,kvo

    关于ios学习中的通知和kvc,kvo案例的整理,基础的oc学习

    iOS中KVC-KVO例子

    iOS中KVC-KVO例子,

    KVC && Runtime

    KVC && Runtime,修改textField placeholder颜色

    KVC的原理和使用

    本demo讲解了KVC的原理和实现,包括定义,执行过程,异常处理,注意事项等

    ios kvo kvc 编程

    英文文档 iso kvo kvc "mvc with less code".

    ios-KVC和KVO学习笔记.zip

    但需要注意的是,键值观察(KVO)是建立在键值编码(Key Value Coding,简称KVC)的基础上,也就是说任何你想使用KVO观察的属性必须符合键值编码。 这个demo主要以字符串、数组为例来学习键值编码和键值观察。 ...

    IOS中Key-Value Coding (KVC)的使用详解(烟台杰瑞教育IOS培训部原创).docx编程资料

    IOS中Key-Value Coding (KVC)的使用详解(烟台杰瑞教育IOS培训部原创).docx编程资料

    ios中整理别人的KVC与KVO代码

    这里是我看别人博客写的kvc与kvo,自己写的代码,本来不打算收费,但是找不到免费的按钮在哪,所以就选了最小的资源分数1.

    iOS-KVC的实现

    KVC全称是Key Value Coding(键值编码),是一个基于NSKeyValueCoding非正式协议实现的机制,它可以直接通过key值对对象的属性进行存取操作,而不需通过调用明确的存取方法。这样就可以在运行时动态在访问和修改对象...

    iOS自定义KVC的实现和使用.zip

    完整地实现了iOS自定义KVC的流程和步骤,并备注详细的说明和解释,方便阅读和理解!

Global site tag (gtag.js) - Google Analytics