1. 程式人生 > >ios學習8_KVC和字典轉模型

ios學習8_KVC和字典轉模型

strong format des source -a ldr orm resource undle

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數組,也是類似的方式。

ios學習8_KVC和字典轉模型