Objective-C 键值编码

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

1. 键值编码

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

valueForKeysetValue: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;
}

2. 键路径

valueForKeyPathsetValueForKeyPath方法访问键路径。

@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;
}

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;
      }
    
  • 快速运算

    键路径不仅能引用对象值,还可以引用一些运算符来进行一些运行。@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.height = %@", [array valueForKeyPath: @"[email protected]"]);
              NSLog(@"avg.height = %@", [array valueForKeyPath: @"[email protected]"]);
              NSLog(@"min.height = %@", [array valueForKeyPath: @"[email protected]"]);
              NSLog(@"max.height = %@", [array valueForKeyPath: @"[email protected]"]);
          }
          return 0;
      }
    
  • 批处理

    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;
    

    }

4. 处理nil和未定义的键

  • (void) setNilValueForKey: (NSString*) key,处理nil值
  • (void) setValue: (id) value forUndefinedKey: (NSString*) key,更改未知键的值
  • (id) valueForUndefinedKey: (NSString*) key,处理未定义的值

你可能感兴趣的:(Objective-C,基础)