zoukankan      html  css  js  c++  java
  • ios学习8_KVC和字典转模型

    Key Value Coding是cocoa的一个标准组成部分,它能让我们能够通过name(key)的方式訪问属性,某些情况下极大地简化了代码。可称之为cocoa的大招。

    例如以下的样例:

    使用KVC的优点

    不使用KVC

    - (id)tableView:(NSTableView *)tableview
    objectValueForTableColumn:(id)column row:(NSInteger)row {
        ChildObject *child = [childrenArray objectAtIndex:row];
        if ([[column identifier] isEqualToString:@"name"]) {
           return [child name];
        }
       if ([[column identifier] isEqualToString:@"age"]) {
           return [child age];
        }
       if ([[column identifier] isEqualToString:@"favoriteColor"]) {   
           return [child favoriteColor];
        }
        // And so on. 
    }

    使用KVC

    - (id)tableView:(NSTableView *)tableview
    objectValueForTableColumn:(id)column row:(NSInteger)row {
        ChildObject *child = [childrenArray objectAtIndex:row];
        return [child valueForKey:[column identifier]];
    }

    显而易见,简化了非常多代码。

    KVC操作

    KVC赋值

    1 给当前对象属性赋值

    - (void)setValue:(id)value forKey:(NSString *)key;

    2给对象的属性的属性赋值

    - (void)setValue:(id)value forKeyPath:(NSString *)keyPath;

    3 处理没有定义的键

    - (void) setValue:(id)value forUndefinedKey:(NSString *)key

    4 字典转模型:会为我们把和dictionary的key名字同样的class proerty设置上dict中key相应的value

    - (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;

    注意:要求字典中的key和对象属性一样。都是主要的OC数据类型:Array/Dictionary/Boolean/Data/Number/String

    KVC取值

    1 获取对象属性的值

    - (id)valueForKey:(NSString *)key;

    2 获取对象属性的属性的值

    - (id)valueForKeyPath:(NSString *)keyPath;

    样例:

    Person * p = [[Person alloc]init];
    Car *car = [[Car alloc]init];
    p.car = car;
    [p setValue:@"qhyuan" forKeyPath:@"name"];
    [p setValue:@(20) forKey:@"id"];
    [p setValue:@"baoshijie" forKeyPath:@"car.brand"];
    [p setValue:@"180000" forKeyPath:@"car.price"];
    NSLog(@"kvc賦值的person对象----%@",p);
    NSString * name = [p valueForKey:@"name"];
    NSString * brand = [p valueForKeyPath:@"car.brand"];
    NSLog(@"%@ %@",name, brand);

    字典转模型

    常规情况


    模型

    Person.h

    @interface Person : NSObject
    @property (nonatomic, copy) NSString * name;
    @property (nonatomic, assign) int age;
    - (instancetype) initWithDict:(NSDictionary *) dict;
    + (instancetype) personWithDict:(NSDictionary *) dict;
    + (NSArray *) person;
    @end
    Person.m

    @implementation Person
    - (instancetype) initWithDict:(NSDictionary *) dict
    {
        if(self = [self init])
    {
    // 使用KVC 字典转模型 如此方便。省去了大量的赋值代码
    [self setValuesForKeysWithDictionary:dict];
        //self.name = dict[@"name"];
        //self.age = [dict[@"age"] integerValue];
        }
        return self;
    }
    + (instancetype) personWithDict:(NSDictionary *) dict
    {
        return [[self alloc]initWithDict:dict];
    }
    + (NSArray *) person
    {
        NSMutableArray * mutablePersons = [NSMutableArray array];
        NSString * path = [[NSBundle mainBundle] pathForResource:@"persons.plist" ofType:nil];
        NSArray *persons = [[NSArray alloc] initWithContentsOfFile:path];
        for (NSDictionary * person in persons) {
            [mutablePersons addObject:[self personWithDict:person]];
        }
        return mutablePersons;
    }
    - (NSString *) description
    {
        NSString * desc = [NSString stringWithFormat:@"<%p:(%@,%d)>",self,self.name,self.age];
        return desc;
    }
    @end

    字典中多个某些key是OC中的keyword


    假设将键age换成了id

    会抛出异常:

    *** Terminating app due to uncaught exception 'NSUnknownKeyException',reason: '[<Person 0x8c419a0> setValue:forUndefinedKey:]: this class isnot key value coding-compliant for the key id.

    重写下面方法就可以,处理没有定义的键

    - (void)setValue:(id)value forUndefinedKey:(NSString *)key;

    解决方案:

    - (void) setValue:(id)value forUndefinedKey:(NSString *)key
    {
        if([key isEqualToString:@"id"])
            key = @"age";
        [super setValue:value forKey:key];
    }

    字典里面还包括某些相应自己定义类的字典或者数组


    Person类添加了一个Car类型的属性

    @property (nonatomic, strong) Car * car;

    我们仅仅须要重写下面方法

    - (void)setValue:(id)value forKey:(NSString *)key;

    解决方法:

    - (void)setValue:(id)value forKey:(NSString *)key
    {
        if([key isEqualToString:@"cars"])
        {
            Car *car = [Car carWithDict:(NSDictionary *)value];
            self.car = car;
        }
        else
            [super setValue:value forKey:key];
    }
    
    打印结果

    字典转模型[5525:60b] (

        "<Person:(zhangsan,20,<Car:(benchi,180000)>)>",

       "<Person:(lisi,22,<Car:(baoma,180000)>)>",

       "<Person:(wangwu,24,<Car:(aodi,180000)>)>"

    )

    假设不仅仅是添加了Cars属性而是添加了Cars数组,也是类似的方式。

  • 相关阅读:
    git 忽略文件 .gitignore 以及规则
    Syncovery : Google Docs protocol completely replaced with Google Drive
    Syncovery 是目前功能最为强大的实时自动备份工具
    FolderSync Instant sync 即时同步
    FolderSync :The various features and how to use them
    How do I use Tasker to run a sync in FolderSync?
    知识共享
    HowTo: Restart SSH Service under Linux / UNIX
    Node.js是一个事件驱动I/O服务端JavaScript环境
    WordPress 客户端软件列表
  • 原文地址:https://www.cnblogs.com/mthoutai/p/6891567.html
Copyright © 2011-2022 走看看