iOS Objective-C 键值编码(九)

首先申明下,本文为笔者学习《Objective-C 基础教程》的笔记,并加入笔者自己的理解和归纳总结。

1. 键值编码

键值编码(Key-Value Coding)是一种间接更改对象状态的方式,简称KVC。

valueForKey:setValue:forKey:分别用来查找属性值和设置属性值。
valueForKey:会把一些基本类型(intfloat等)自动装箱,返回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,处理未定义的值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值