zoukankan      html  css  js  c++  java
  • iOS开发基础-KVC简单介绍

    一、KVC介绍

      键值编码(Key Value Coding,KVC):使开发者不必进行任何操作就可以进行属性的动态读写。

      KVC操作方法由 NSKeyValueCoding 协议提供,而 NSObject 实现了这个协议,因此 ObjC 中几乎所有的对象都支持KVC操作,常用的操作方法如下:

    1)动态设置: setValue:forKey: 用于简单路径, setValue:forKeyPath: 用于复合路径。如 Person 类有一个 Account 类型的属性,那么 Person.Account 就是一个复合属性。

    2)动态读取: valueForKey: 、 valueForKeyPath: 。

      补充:键值观察(Key Value Observer,KVO):监听某一个模型的属性,只要该模型属性的值发生变化就通知你。

    二、代码实例1

      新建 Command Line Tool 项目,并命名为 KVCDemo 。紧接着,为项目添加一个继承自 NSObject 类的 Person 类,为该新类添加名字和年龄属性,如下:

    1 //Person.h
    2 @property (nonatomic, copy) NSString *name;
    3 @property (nonatomic, assign) int age;

      在 Person 类的实现文件中重写 description 方法:

    1 //Person.m
    2 - (NSString *)description {
    3     return [NSString stringWithFormat:@"<%@:%p>, {name:%@, age:%d}.", [self class], self, self.name, self.age];
    4 }

      上述中 %p 指代指针。

      在 main.m 文件中对 Person 进行简单的处理:

     1 //main.m
     2 int main(int argc, const char * argv[]) {
     3     @autoreleasepool {
     4         Person *p1 = [[Person alloc] init];
     5         [p1 setValue:@"WJQ" forKey:@"name"];
     6         [p1 setValue:@"23" forKey:@"age"];
     7         
     8         Person *p2 = [[Person alloc] init];
     9         [p2 setValue:@"LWX" forKey:@"name"];
    10         [p2 setValue:@"22" forKey:@"age"];
    11         NSLog(@"%@. %@.", p1, [p2 valueForKey:@"name"]);
    12     }
    13     return 0;
    14 }

      使用 setValue:forKey: 进行KVC操作时,系统会自动判断对象属性的类型并完成转换,如上例将 @"23" 转换为 23 。

      输出为:

    <Person:0x1006001c0>, {name:WJQ, age:23}.. LWX.

    三、代码实例2

      如何生成只包含 name 属性的数组,并打印出来?

      在 main.m 文件中中导入 Person 类的头文件,并修改 main 函数的代码:

     1 int main(int argc, const char * argv[]) {
     2     @autoreleasepool {
     3         Person *p1 = [[Person alloc] init];
     4         [p1 setValue:@"WJQ" forKey:@"name"];
     5         [p1 setValue:@"23" forKey:@"age"];
     6         
     7         Person *p2 = [[Person alloc] init];
     8         [p2 setValue:@"LWX" forKey:@"name"];
     9         [p2 setValue:@"22" forKey:@"age"];
    10         
    11         NSArray *persons = @[p1, p2];   //创建Person对象的数组
    12         NSLog(@"%@", persons);
    13         NSMutableArray *arrayM = [NSMutableArray array];    //用于存放各个Person的name
    14         for (Person *p in persons) {
    15             [arrayM addObject:[p valueForKeyPath:@"name"]];
    16         }
    17         NSLog(@"%@", arrayM);
    18     }
    19     return 0;
    20 }

      输出为:

    (
        "<Person:0x100208dc0>, {name:WJQ, age:23}.",
        "<Person:0x100209c80>, {name:LWX, age:22}."
    )
    (
        WJQ,
        LWX
    )

      由于使用KVC按键值路径取值时,如果对象不包含指定的键值,会自动进入对象内部,查找对象的属性。在不改变输出的情况下,修改上述代码为:

     1 int main(int argc, const char * argv[]) {
     2     @autoreleasepool {
     3         Person *p1 = [[Person alloc] init];
     4         [p1 setValue:@"WJQ" forKey:@"name"];
     5         [p1 setValue:@"23" forKey:@"age"];
     6         
     7         Person *p2 = [[Person alloc] init];
     8         [p2 setValue:@"LWX" forKey:@"name"];
     9         [p2 setValue:@"22" forKey:@"age"];
    10         
    11         NSArray *persons = @[p1, p2];   //创建Person对象的数组
    12         NSLog(@"%@", persons);
    13         NSMutableArray *arrayM = [NSMutableArray array];    //用于存放各个Person的name
    14         [arrayM addObject:[persons valueForKeyPath:@"name"]];
    15         NSLog(@"%@", arrayM);
    16     }
    17     return 0;
    18 }

    三、代码实例3

      演示根据键值路径取值,KVC机制会自动层层深入,并获取对应的键值。

      为项目新建一个 Book 类继承自 NSObject ,添加 bookName 属性:

    1 //Book.h
    2 @property(nonatomic, copy) NSString *bookName;

      修改 Book 类的 description 方法:

    1 //Book.m
    2 - (NSString *)description {
    3     return [NSString stringWithFormat:@"<%@, %p>, {bookName:%@}", [self class], self, self.bookName];
    4 }

      接着在 Person 类的头文件中导入 Book.h ,再添加一个 Book 类的对象属性,如下:

    1 //Person.h
    2 @property (nonatomic, strong) Book *book;

      修改 Person 类的 description 方法,使其输出 book 属性:

    1 //Person.m
    2 - (NSString *)description {
    3     return [NSString stringWithFormat:@"<%@:%p>, {name:%@, age:%d, book:%@}.", [self class], self, self.name, self.age, self.book];
    4 }

      最后,修改 main 函数:

     1 //main.m
     2 int main(int argc, const char * argv[]) {
     3     @autoreleasepool {
     4         Person *p1 = [[Person alloc] init];
     5         [p1 setValue:@"WJQ" forKey:@"name"];
     6         [p1 setValue:@"23" forKey:@"age"];
     7         Book *b1 = [[Book alloc] init];
     8         b1.bookName = @"iPhone";
     9         p1.book = b1;
    10         
    11         Person *p2 = [[Person alloc] init];
    12         [p2 setValue:@"LWX" forKey:@"name"];
    13         [p2 setValue:@"22" forKey:@"age"];
    14         Book *b2 = [[Book alloc] init];
    15         b2.bookName = @"iOS";
    16         p2.book = b2;
    17         
    18         NSArray *persons = @[p1, p2];   //创建Person对象的数组
    19         NSLog(@"%@", persons);
    20         NSArray *arrayM = [persons valueForKeyPath:@"book.bookName"];
    21         NSLog(@"%@", arrayM);
    22     }
    23     return 0;
    24 }

      输出为:

    (
        "<Person:0x1002095d0>, {name:WJQ, age:23, book:<Book, 0x10020c4c0>, {bookName:iPhone}}.",
        "<Person:0x10020c520>, {name:LWX, age:22, book:<Book, 0x10020c540>, {bookName:iOS}}."
    )
    (
        iPhone,
        iOS
    )

    参考博客:ios开发UI篇—Kvc简单介绍

    实例代码:http://pan.baidu.com/s/1dDYZAOL

  • 相关阅读:
    如何在一个页面调用另一个页面
    CSS3新增的选择器和属性
    js中函数和方法的区别
    jQuery中哪几种选择器
    关于JS数组的栈和队列操作
    HDU1232 畅通工程(并查集)
    并查集
    有关素数的基础算法
    二分教室
    蚂蚁下桥(思维)
  • 原文地址:https://www.cnblogs.com/wjq-Law/p/5135497.html
Copyright © 2011-2022 走看看