Objective-C中的KVC与KVO(上)

原创 2012年03月30日 23:32:12

Objective-C中的KVC与KVO是两种比较重要的技术,这里简要介绍一下这两者的使用方法。

一、KVC

《iOS程序开发方法与实践》中介绍了KVC(Key–Value Coding,键值编码)的基本内容。

简要来说,KVC提供了一种在运行时而非编译时动态访问对象属性与成员变量的方式,也就是说,我们可以用字符串的内容作为属性名称或者成员变量名称进行访问。这种特性有些类似于其他高级编程语言中的反射。

举个例子,例如我们创建了一个类ClassA,其中定义了3个属性p1、p2和p3,以及1个实例方法getValueByPropertyName:,代码如下:

@interface ClassA : NSObject
@property (nonatomic) int p1;
@property (nonatomic) int p2;
@property (nonatomic) int p3;

- (int)getValueByPropertyName:(NSString*)pName;
@end

@implementation ClassA
@synthesize p1 = _p1, p2 = _p2, p3 = _p3;

...
- (int)getValueByPropertyName:(NSString*)pName
{
    if([pName isEqualToString:@"p1"])
    {
        return self.p1;
    }
    else if([pName isEqualToString:@"p2"])
    {
        return self.p2;
    }
    else if([pName isEqualToString:@"p3"])
    {
        return self.p3;
    }
    
    return 0;
}
@end

方法getValueByPropertyName:用于通过字符串来访问对应的属性值。如果我们想要向ClassA添加几个属性,那么这个方法就还需要添加几个else if语句。而如果使用KVC就会方便许多,代码如下:

- (int)getValueByPropertyName:(NSString*)pName
{
    NSNumber* pNumber = [self valueForKey:pName];
    return [pNumber intValue];
}

这里有几点需要注意,首先这里的valueForKey:方法用于以字符串调用对象的get属性方法,或者读取成员变量的值;与之相对的是setValue:forKey:,它用于以字符串调用对象的set属性方法,或者修改成员变量的值。第二点需要注意的是,对于基本数据类型,KVC方法会对基本数据类型进行封装(基本数据类型封装为NSNumber,其他结构体类型封装为NSValue)。这里的p1、p2、p3定义为int型,而valueForKey:方法返回的是NSNumber对象,需要再调用intValue取出其中的值。setValue:forKey:方法与之类似,接收NSNumber参数。第三,在使用KVC时,如果找不到字符串对应的属性和成员变量时会怎么样?此时会调用valueForUndefinedKey:或者setValue:forUndefinedKey:这两个方法,默认情况下会抛出异常。第四,默认情况下KVC方法能够直接访问类的私有成员变量,如果我们不想这样,可以重写accessInstanceVariablesDirectly方法,并令其返回NO(默认是返回YES)。KVC方法定义在NSKeyValueCoding类别中,该类别附加于NSObject类上,所以所有对象都具有这些方法。第五,在一些特殊的类的对象上调用KVC方法会有特别的效果。对于数组NSArray、集合NSSet,调用valueForKey:会对每个数组和集合成员调用valueForKey:,并返回新的数组或者集合。

在KVC中还有一种常用技术,称为键值链(Key Path)。键值链是用点将若干键相连的字符串,例如“manufacturer.product.name”。通过在对象上调用valueForKeyPath:或者setValue:forKeyPath:,我们就可以在一条语句中接连调用制定的属性。请看下面的例子:

@interface Product : NSObject
@property NSString* name;
@end

@implementation Product
@synthesize name = _name;

- (void)dealloc
{
    self.name = nil;
    [super dealloc];
}
@end

@interface Manufacturer : NSObject
@property Product* product;
@end

@implementation Manufacturer
@synthesize product = _product;

-(void)dealloc
{
    self.product = nil;
    [super dealloc];
}
@end

int main(int argc, const char * argv[])
{

    @autoreleasepool
    {
        Manufacturer* apple = [[[Manufacturer alloc] init] autorelease];
        Product* iPhone4S = [[[Product alloc] init] autorelease];
        iPhone4S.name = @"iPhone 4S";
        apple.product = iPhone4S;
        
        Manufacturer* micro$oft = [[[Manufacturer alloc] init] autorelease];
        Product* win8 = [[[Product alloc] init] autorelease];
        win8.name = @"Windows 8";
        micro$oft.product = win8;
        
        NSArray* manufacturerArray = [NSArray arrayWithObjects:apple, micro$oft, nil];
        
        NSArray* productNameArray = [manufacturerArray valueForKeyPath:@"product.name"];
        NSLog(@"productNameArray:\n%@", productNameArray);
        
    }
    return 0;
}
首先程序定义了两个类Product与Manufacturer,分别定义商品与制造商。Manufacturer类定义了一个product属性,Product类定义了name属性。在main函数中,我们创建了两个制造商苹果和微软,以及两个商品iPhone4S和Win8,并设置好他们之间的关系。然后程序将两个制造商放入数组中,在数组上调用valueForKeyPath:方法并传入键值链@"product.name"。于是数组首先执行valueForKey:@"product",它会在每个数组成员上调用product属性,获取每个制造商的商品,然后再在每个商品上调用valueForKey:@"name",获取每个制造商的每个商品的名称,并将结果放到另一个数组中。上述程序的输出结果为:
productNameArray:
(
    "iPhone 4S",
    "Windows 8"
)

使用KVC的好处是非常灵活,但同时也丢失了编译时检查。

在下一篇中,我将会介绍KVO的使用方法。

相关文章推荐

[iOS]Objective-C之KVC、KVO

概述 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby、Python的动态特性,例如动态类型、动态加载、动态绑定等。今天我们着重介绍ObjC中的键值编码(KVC)、键值...

(转)iOS编程——Objective-C KVO/KVC机制

1.     1 .Person类  2.     @implementation Person  3.     @synthesize name,age;//属性name 将被监视  ...
  • L__0omg
  • L__0omg
  • 2013年02月04日 14:31
  • 480

IOS开发系列--Objective-C之KVC、KVO

概述 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby、Python的动态特性,例如动态类型、动态加载、动态绑定等。今天我们着重介绍ObjC中的键值编码(KVC)、键值...

移动开发(IOS) – Objective-C-10-KVC、谓词、KVO与通知

移动开发(IOS) – Objective-C-10-KVC、谓词、KVO与通知 By docoder in 博客, 学习 on 2014/05/31 1.KVC 1.1.基本概念...

转载大神IOS开发系列【6】--Objective-C之KVC、KVO

转载自:http://www.cnblogs.com/kenshincui/p/3871178.html 概述 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于R...

Objective-C KVC/KVO NSNotification(通知)的简单理解与应用

KVC :Key-Value Coding 键值编码 KVO :Key-Value Observing 键值观察 NSNotificationCenter 通知...

iOS开发系列--Objective-C之KVC、KVO

概述 由于ObjC主要基于Smalltalk进行设计,因此它有很多类似于Ruby、Python的动态特性,例如动态类型、动态加载、动态绑定等。今天我们着重介绍ObjC中的键值编码(KVC)、键值...

Objective-C KVO&KVC

Key-Value Observing 快速入门 翻译:杨登峰 (dengfengyang@gmail.com) 时间:2010-03-12 转帖请注明转之 苹果开发中文网(http...

Objective-c KVC and KVO and 通知

一、  目标:1、会使用 KVC KVO  2、了解 通知 1、KVC:字符串 表征机制  KVC可以用来访问和设置属性的值。 2、任何对象都可以 进行键值 编码。 3、KVO:当对象 属性值 ...

深入理解Objective-C:KVC&KVO

KVC一、 KVC 介绍KVC也就是key-value-coding,即键值编码,说白了就是通过指定的key获得想要的值value。而不是通过调用setter、getter方法访问。二、 KVC 的强...
  • WiKi_Su
  • WiKi_Su
  • 2017年08月08日 18:51
  • 388
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Objective-C中的KVC与KVO(上)
举报原因:
原因补充:

(最多只允许输入30个字)