IOS开发之旅-KVC【键值编码】

  在日常开发中,读取修改对象的属性值时,通常是点调用对应的属性进行相关操作。另外一种方式是通过键值编码,简称KVC,在键值编码中主要使用以下方法

   /* Given a key that identifies an attribute or to-one relationship, return the attribute value or the related object. Given a key that identifies a to-many relationship, return an immutable array or an immutable set that contains all of the related objects.*/

- (id)valueForKey:(NSString *)key;

/* Given a value and a key that identifies an attribute, set the value of the attribute. Given an object and a key that identifies a to-one relationship, relate the object to the receiver, unrelating the previously related object if there was one. Given a collection object and a key that identifies a to-many relationship, relate the objects contained in the collection to the receiver, unrelating previously related objects if there were any.*/

- (void)setValue:(id)value forKey:(NSString *)key;

/* Key-path-taking variants of like-named methods. The default implementation of each parses the key path enough to determine whether or not it has more than one component (key path components are separated by periods). If so, -valueForKey: is invoked with the first key path component as the argument, and the method being invoked is invoked recursively on the result, with the remainder of the key path passed as an argument. If not, the like-named non-key-path-taking method is invoked.*/

- (id)valueForKeyPath:(NSString *)keyPath;

- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;

/* Given that an invocation of -valueForKey: would be unable to get a keyed value using its default access mechanism, return the keyed value using some other mechanism. The default implementation of this method raises an NSUndefinedKeyException. You can override it to handle properties that are dynamically defined at run-time.*/

- (id)valueForUndefinedKey:(NSString *)key;

/* Given that an invocation of -setValue:forKey: would be unable to set the keyed value using its default mechanism, set the keyed value using some other mechanism. The default implementation of this method raises an NSUndefinedKeyException. You can override it to handle properties that are dynamically defined at run-time*/

- (void)setValue:(id)value forUndefinedKey:(NSString *)key;

/* Given that an invocation of -setValue:forKey: would be unable to set the keyed value because the type of the parameter of the corresponding accessor method is an NSNumber scalar type or NSValue structure type but the value is nil, set the keyed value using some other mechanism. The default implementation of this method raises an NSInvalidArgumentException. You can override it to map nil values to something meaningful in the context of your application.*/

- (void)setNilValueForKey:(NSString *)key;

/* Given a dictionary containing keyed attribute values, to-one-related objects, and/or collections of to-many-related objects, set the keyed values. Dictionary entries whose values are NSNull result in -setValue:nil forKey:key messages being sent to the receiver.*/

- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;

/* Given an array of keys, return a dictionary containing the keyed attribute values, to-one-related objects, and/or collections of to-many-related objects. Entries for which -valueForKey: returns nil have NSNull as their value in the returned dictionary.*/

- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;

下面以实例演示KVC,Person.h:

#import <Foundation/Foundation.h>

@interface Person : NSObject

-(id) initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName age:(int)age;

@property (nonatomic,copy) NSString *firstName;
@property (nonatomic,copy) NSString *lastName;
@property (nonatomic,strong) Person *father;
@property int age;

@end

Person.m:

#import "Person.h"

@implementation Person

-(id)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName age:(int)age
{
    if(self = [super init])
    {
        self.firstName  = firstName;
        self.lastName   = lastName;
        self.age        = age;
    }
    return self;
}

//invoked by (setValue:forKey:) method,when it‘s given a nil value for a scalar value (such as int or float)
-(void)setNilValueForKey:(NSString *)key
{
    if([key isEqualToString:@"age"])
    {
        [self setValue:@18 forKey:@"age"];
    }
    else
    {
        [super setNilValueForKey:key];
    }
}

//invoked by (setValue:forKey:) method,when it finds no property corresponding to a given value
-(void)setValue:(id)value forUndefinedKey:(NSString *)key
{
    NSLog(@"%@ property not found",key);
}

//invoked by (valueForKey:) method,when it finds no property corresponding to a given value
-(id)valueForUndefinedKey:(NSString *)key
{
    NSLog(@"%@ property not found",key);
    return nil;
}

-(NSString *) description
{
    NSString *desc = [[NSString alloc] initWithFormat:@"firstName: %@, lastName:%@, age: %i", self.firstName,self.lastName,self.age];
    return desc;
}

@end

测试代码:

#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *person = [[Person alloc]initWithFirstName:@"xiao" lastName:@"long" age:26];
        NSLog(@"%@",person);
        //firstName: xiao, lastName:long, age: 26

        NSLog(@"%@",[person valueForKey:@"firstName"]);
        // xiao

        [person setValue:@"quan" forKey:@"lastName"];
        NSLog(@"%@",person.lastName);
        //quan

        //middlenName 属性不存在,则调用Person类的【-(void)setValue:(id)value forUndefinedKey:(NSString *)key】
        [person setValue:@"pstune" forKey:@"middleName"];
        //middleName property not found

        //middlenName 属性不存在,则调用Person类的【-(id)valueForUndefinedKey:(NSString *)key】
        [person valueForUndefinedKey:@"middleName"];
        //middleName property not found

        //age 是值类型,不能够设置nil,所以调用Person类的【-(void)setNilValueForKey:(NSString *)key】
        [person setValue:nil forKey:@"age"];
        NSLog(@"%@",person);
        //firstName: xiao, lastName:quan, age: 18

        Person *father = [[Person alloc]initWithFirstName:@"father" lastName:@"dad" age:50];
        person.father = father;

        NSLog(@"father firstName: %@",[person valueForKeyPath:@"father.firstName"]);
        //father firstName: father

        [person setValue:@"quan" forKeyPath:@"father.lastName"];
        NSLog(@"%@",father);
        //firstName: father, lastName:quan, age: 50

        NSDictionary *propertyDic = [person dictionaryWithValuesForKeys:@[@"firstName",@"lastName"]];
        NSLog(@"%@",propertyDic);
        /*
         {
         firstName = xiao;
         lastName = quan;
         }
         */

        [person setValuesForKeysWithDictionary:@{@"firstName":@"pstune",@"lastName":@"web"}];
        NSLog(@"%@",person);
        //firstName: pstune, lastName:web, age: 18

    }
    return 0;
}

KVC总结:

  • 对于KVC,Cocoa会自动装箱和开箱标量值(int,float,double)
  • -(id) valueForKey: (NSString*) key首先会查找以参数命名的getter方法,如果不存在这样的方法,将会继续在对象内查找名称格式为_key或key的实例变量
  • -(id) valueForKey: (NSString*) key在Objective-C运行时中使用元数据打开对象并进入其中查找需要的信息。
时间: 2024-08-27 09:17:06

IOS开发之旅-KVC【键值编码】的相关文章

Objective-C(十七、KVC键值编码及实例说明)——iOS开发基础

结合之前的学习笔记以及参考<Objective-C编程全解(第三版)>,对Objective-C知识点进行梳理总结.知识点一直在变,只是作为参考,以苹果官方文档为准~ 十七.键值编码 KVC 关于KVC的知识点将通过下列例子来展开说明: Person.h文件,Person类拥有name和age两个成员变量 @interface Person : NSObject { @private NSString *_name; NSInteger _age; } - (void)setAge:(NSIn

KVC - 键值编码

[基本概念] 1.键值编码是一个用于间接访问对象属性的机制,使用该机制不需要调用存取方法和变量实例就可访问对象属性. 2.键值编码方法在OC非正式协议(类目)NSKeyValueCoding中被声明,默认的实现方法由NSObject提供. 3.键值编码支持带有对象值的属性,同时也支持纯数值类型和结构.非对象参数和返回类型会被识别并自动封装/解封. [键值访问] 键值编码中的基本调用包括-valueForKey: 和 -setValue:forkey: 这两个方法,它们以字符串的形式向对象发送消息

iOS开发UI之KVC(取值/赋值) - KVO (观察某个对象的某个属性的改变)

一. KVC : key value coding,通常用来给某一个对象的属性赋值 1. KVC赋值 // 1.1 创建人 LDPerson *p = [[LDPerson alloc] init]; self.person = p; // 1.2 创建狗 LDDog *dog = [[LDDog alloc] init]; // 1.3 将狗赋值给人 [p setValue:dog forKeyPath:@"dog"]; // 1.4 通过kvc给dog的weight属性赋值 \ 赋

IOS开发info.plist中键值的含义

1.     Application does not run in background(鍵名:UIApplicationExistsOnSuspend)自從iOS4.0之後,當你在應用程式執行的時候按下Home鍵,應用程式並不會中斷目前的執行,而是躲到背景去了.因此希望使用者在按下Home鍵之後就要中斷目前程式的執行,請勾選這個選項. 2.     Application requires iPhone environment(鍵名:LSRequiresIPhoneOS)iOS的家族繫ㄌㄧ誒

关于KVC键值编码

转载自http://www.tuicool.com/articles/2aYfy2 Key-value coding,它是一种使用字符串标识符,间接访问对象属性的机制,而不是直接调用getter 和 setter方法.通常我们使用valueForKey 来替代getter 方法,setValue:forKey来代替setter方法. 首先来看一看KVC与setter,getter方法赋值的区别 Persion *person = [ [Person alloc] init ]; //不使用KVC

ios中键值编码kvc和键值监听kvo的特性及详解

总结: kvc键值编码  1.就是在oc中可以对属性进行动态读写(以往都是自己赋值属性)           2. 如果方法属性的关键字和需要数据中的关键字相同的话                  3. 动态设置:setValue:属性值 forKey:属性名(用于简单的路径)/setValue:属性值 forKeyPath:属性名(用于复杂的路径)kvo键值监听  永久性的监听item属性值的改变,如果改变就从新设置             1.监听方法:[addObserver:self

IOS开发——UI基础-KVC

除了一般的赋值和取值的方法,我们还可以用Key-Value-Coding(KVC)键值编码来访问你要存取的类的属性. 如何使用KVC存取对象属性呢?看个示例 一.使用KVC存数据 定义一个person类 .h文件 #import <Foundation/Foundation.h> @class Dog; @interface Person : NSObject /** 姓名*/ @property (nonatomic, copy)NSString *name; /** 钱*/ @proper

iOS学习笔记(6)键值编码——KVC

在KVC编程方式中,无论调用setValue:forKey:方法,还是调用valueForKey:方法,都是通过NSString对象来指定被操作属性,其中forKey:标签用户传入属性名的. 对于setValue:属性值[email protected]“name”;代码,底层的执行机制如下. (1)程序优先考虑调用“setName:属性值;”代码通过setter方法完成设置. (2)如果该类没有setName:方法,KVC机制会搜索该类名为_name的成员变量,无论该成员变量是在类接口部分定义

OC8-属性 KVC是键值编码

1.属性,是oc提供的一种快速的模式化的创建实例变量的方式. (1)属性是通过@property标记的, (2)属性会在背后,默默的帮我们做set和get方法 2.属性做的工作 (1)创建一个实例变量,名字是下划线加属性名, (2)帮我们自动get和setter 的方式,创建一组方法, 3.点语法,点语法是专门为了setter 和getter 方法配备的一种语法糖.会自动根据语法和语境调用是哪一种方法, (1) (.)其实就是转换成了getter 和setter 方法,p.hobby.lengt