首先申明下,本文为笔者学习《Objective-C 基础教程》的笔记,并加入笔者自己的理解和归纳总结。
1. 键值编码
键值编码(Key-Value Coding)是一种间接更改对象状态的方式,简称KVC。
valueForKey:
和setValue:forKey:
分别用来查找属性值和设置属性值。
valueForKey:
会把一些基本类型(int
、float
等)自动装箱,返回NSNumber
等类型。
调用setValue:forKey:
时要把那些基本类型主动装箱。
@interface ShapeBounds : NSObject {
int width;
int height;
}
@end
@implementation ShapeBounds
- (NSString *)description {
return [NSString stringWithFormat:@"(%d, %d)", width, height];
}
@end
int main(int argc, const char* argv[]) {
@autoreleasepool {
ShapeBounds *bounds = [[ShapeBounds alloc] init];
NSLog(@"%@", bounds);
[bounds setValue:[NSNumber numberWithInt:20] forKey:@"width"];
[bounds setValue:[NSNumber numberWithInt:30] forKey:@"height"];
NSLog(@"%@", bounds);
NSLog(@"width = %@, height = %@", [bounds valueForKey:@"width"],
[bounds valueForKey:@"height"]);
}
return 0;
}
输出
(0, 0)
(20, 30)
width = 20, height = 30
2. 键路径
valueForKeyPath:
和setValueForKeyPath:
方法访问键路径。
@interface Shape : NSObject {
ShapeBounds *bounds;
}
@end
@implementation Shape
- (id)init {
if (self = [super init]) {
bounds = [[ShapeBounds alloc] init];
}
return self;
}
- (NSString *)description {
return [NSString stringWithFormat:@"Shape bounds = %@", bounds];
}
@end
int main(int argc, const char* argv[]) {
@autoreleasepool {
Shape *shape = [[Shape alloc] init];
NSLog(@"%@", shape);
[shape setValue:[NSNumber numberWithInt:20] forKeyPath:@"bounds.width"];
[shape setValue:[NSNumber numberWithInt:30] forKeyPath:@"bounds.height"];
NSLog(@"%@", shape);
NSLog(@"width = %@, height = %@", [shape valueForKeyPath:@"bounds.width"],
[shape valueForKeyPath:@"bounds.height"]);
}
return 0;
}
输出
Shape bounds = (0, 0)
Shape bounds = (20, 30)
width = 20, height = 30
3. 整体操作
整体访问
访问NSArray
数组中的某个键值,存在一对多的情况,返回一个数组。
Shape * createShape(int width, int height) {
Shape *shape = [[Shape alloc] init];
[shape setValue:[NSNumber numberWithInt:width] forKeyPath:@"bounds.width"];
[shape setValue:[NSNumber numberWithInt:height] forKeyPath:@"bounds.height"];
return shape;
}
int main(int argc, const char* argv[]) {
@autoreleasepool {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:17];
[array addObject:createShape(20, 30)];
[array addObject:createShape(40, 50)];
[array addObject:createShape(60, 45)];
NSLog(@"width = %@", [array valueForKeyPath:@"bounds.width"]);
NSLog(@"height = %@", [array valueForKeyPath:@"bounds.height"]);
}
return 0;
}
输出
width = (
20,
40,
60
)
height = (
30,
50,
45
)
快速运算
键路径不仅能引用对象值,还可以引用一些运算符来进行一些运行。@count
,总数。@sum
,总值。@avg
,平均值。@min
,最小值。@max
,最大值。
int main(int argc, const char* argv[]) {
@autoreleasepool {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:17];
[array addObject:createShape(20, 30)];
[array addObject:createShape(40, 50)];
[array addObject:createShape(60, 45)];
NSLog(@"count = %@", [array valueForKeyPath:@"bounds.@count"]);
NSLog(@"sum.width = %@", [array valueForKeyPath:@"bounds.@sum.width"]);
NSLog(@"avg.width = %@", [array valueForKeyPath:@"bounds.@avg.width"]);
NSLog(@"min.width = %@", [array valueForKeyPath:@"bounds.@min.width"]);
NSLog(@"max.width = %@", [array valueForKeyPath:@"bounds.@max.width"]);
}
return 0;
}
输出
count = 3
sum.width = 120
avg.width = 40
min.width = 20
max.width = 60
批处理
dictionaryWithValuesForKeys:
,接收一个字符串数组,对每个键使用valueForKey:
方法。
setValuesForKeysWithDictionary:
,接收一个字典,调用setValue:forKey:
方法。
int main(int argc, const char* argv[]) {
@autoreleasepool {
ShapeBounds *bounds = [[ShapeBounds alloc] init];
[bounds setValue:[NSNumber numberWithInt:20] forKey:@"width"];
[bounds setValue:[NSNumber numberWithInt:30] forKey:@"height"];
NSLog(@"%@", bounds);
NSArray *array = [NSArray arrayWithObjects:@"width", @"height", nil];
NSDictionary *dict = [bounds dictionaryWithValuesForKeys:array];
NSLog(@"dict = %@", dict);
NSDictionary *newDict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:40], @"width",
[NSNumber numberWithInt:50], @"height", nil];
[bounds setValuesForKeysWithDictionary:newDict];
NSLog(@"%@", bounds);
}
return 0;
}
输出
(20, 30)
dict = {
height = 30;
width = 20;
}
(40, 50)
4. 处理nil和未定义的键
(void)setNilValueForKey:(NSString *)key
,处理nil值(void)setValue:(id)value forUndefinedKey:(NSString *)key
,更改未知键的值(id)valueForUndefinedKey:(NSString *)key
,处理未定义的值