第十四章 REST解惑——初识KVC

来源:互联网 发布:123d软件下载 编辑:程序博客网 时间:2024/05/20 18:49

一.KVC的基本概念

Key-value coding,它是一种使用字符串标识符,间接访问对象属性的机制,而不是直接调用getter 和 setter方法。通常我们使用valueForKey 来替代getter 方法,setValue:forKey来代替setter方法。


下面,给大家一个例子,基础流程是这样的:

首先,创建基类,主要方法:

//根据这个来把key-value 自动分配到对应的属性- (id) initWithDictionary:(NSMutableDictionary *) jsonObject;




然后,创建model类,继承自基类

model类需要实现方法

//如果遇到字典的key与model类中的属性名称不对应的情况,需要自己处理- (void)setValue:(id)value forUndefinedKey:(NSString *)key//一般的赋值,key与model类中的属性名相同,处理一些特殊逻辑- (void)setValue:(id)value forKey:(NSString *)key



各位还是通过代码来看下吧:

基类:JSONModel.h 

////  JSONModel.h//  iHotelApp_Demo////  Created by Eric on 14-1-13.//  Copyright (c) 2014年 Eric. All rights reserved.//#import <Foundation/Foundation.h>@interface JSONModel : NSObject<NSCopying,NSCoding,NSMutableCopying>{}- (id) initWithDictionary:(NSMutableDictionary *) jsonObject;@end

JSONModel.m

////  JSONModel.m//  iHotelApp_Demo////  Created by Eric on 14-1-13.//  Copyright (c) 2014年 Eric. All rights reserved.//#import "JSONModel.h"@implementation JSONModel//根据字典初始化- (id)initWithDictionary:(NSMutableDictionary *)jsonObject{    self = [super init];    if (self)    {        [self setValuesForKeysWithDictionary:jsonObject];    }    return self;}//允许编码- (BOOL) allowsKeyedCoding{    return YES;}- (id) initWithCoder:(NSCoder *)aDecoder{    return self;}- (void)encodeWithCoder:(NSCoder *)aCoder{    //do nothing}//复制一个副本- (id)mutableCopyWithZone:(NSZone *)zone{    JSONModel *newModel = [[JSONModel allocWithZone:zone] init];    return newModel;}//复制一个副本- (id)copyWithZone:(NSZone *)zone{    JSONModel *newModel = [[[self class] allocWithZone:zone] init];    return newModel;}//找未找到的Key- (id) valueForUndefinedKey:(NSString *)key{    NSLog(@"Undefined Key: %@",key);    return nil;}//设置未找到的Key- (void)setValue:(id)value forUndefinedKey:(NSString *)key{    NSLog(@"Undefined Key: %@",key);}@end

实体类:MenuItem.h    JSONModel的子类。

////  MenuItem.h//  iHotelApp_Demo////  Created by Eric on 14-1-14.//  Copyright (c) 2014年 Eric. All rights reserved.//#import "JSONModel.h"#import <Foundation/Foundation.h>/* "id": "JAP122", "image": "http://d1.myhotel.com/food_image1.jpg", "name": "Teriyaki Bento", "spicyLevel": 2, "rating" : 4, "description" : "Teriyaki Bento is one of the best lorem ipsum dolor sit", "waitingTime" : "930", "reviewCount" : 4 */@interface MenuItem : JSONModel@property (nonatomic,strong) NSString *itemId;@property (nonatomic,strong) NSString *image;@property (nonatomic,strong) NSString *name;@property (nonatomic,strong) NSString *spicyLevel;@property (nonatomic,strong) NSString *rating;@property (nonatomic,strong) NSString *itemDescription;@property (nonatomic,strong) NSString *waitingTime;@property (nonatomic,strong) NSString *reviewCount;@property (nonatomic,strong) NSMutableArray *reviews;@end

MenuItem.m

MenuItem 自定义实现解码,编码的方法,这样,基类JSONModel中的

initWithDictionary方法,便可以实现key-value与类属性的相对应

////  MenuItem.m//  iHotelApp_Demo////  Created by Eric on 14-1-14.//  Copyright (c) 2014年 Eric. All rights reserved.//#import "MenuItem.h"#import "Review.h"@implementation MenuItem- (id)init{    self = [super init];    if (self) {        self.reviews = [NSMutableArray array];    }    return self;}//在赋值的过程中,如果发现未声明的Key- (void)setValue:(id)value forUndefinedKey:(NSString *)key{    if ([key isEqualToString:@"id"]) {        self.itemId = value;    } else if([key isEqualToString:@"description"]){        self.itemDescription = value;    }else{        [super setValue:value forUndefinedKey:key];    }}//赋值- (void)setValue:(id)value forKey:(NSString *)key{    if ([key isEqualToString:@"reviews"]) {        for (NSMutableDictionary *reviewArrayDic in value) {            Review *thisReview = [[Review alloc] initWithDictionary:reviewArrayDic];            [self.reviews addObject:thisReview];        }    }else{        [super setValue:value forKey:key];    }}- (void)encodeWithCoder:(NSCoder *)aCoder{    [aCoder encodeObject:self.itemId forKey:@"itemId"];    [aCoder encodeObject:self.image forKey:@"image"];    [aCoder encodeObject:self.name forKey:@"name"];    [aCoder encodeObject:self.spicyLevel forKey:@"spicyLevel"];    [aCoder encodeObject:self.rating forKey:@"rating"];    [aCoder encodeObject:self.itemDescription forKey:@"itemDescription"];    [aCoder encodeObject:self.waitingTime forKey:@"waitingTime"];    [aCoder encodeObject:self.reviewCount forKey:@"reviewCount"];    [aCoder encodeObject:self.reviews forKey:@"reviews"];}- (id)initWithCoder:(NSCoder *)decoder{    self = [super init];    if (self) {        self.itemId = [decoder decodeObjectForKey:@"itemId"];        self.image = [decoder decodeObjectForKey:@"image"];        self.name = [decoder decodeObjectForKey:@"name"];        self.spicyLevel = [decoder decodeObjectForKey:@"spicyLevel"];        self.rating = [decoder decodeObjectForKey:@"rating"];        self.itemDescription = [decoder decodeObjectForKey:@"itemDescription"];        self.waitingTime = [decoder decodeObjectForKey:@"waitingTime"];        self.reviewCount = [decoder decodeObjectForKey:@"reviewCount"];        self.reviews = [decoder decodeObjectForKey:@"reviews"];    }    return self;}- (id)copyWithZone:(NSZone *)zone{    id theCopy = [[[self class] allocWithZone:zone] init];  // use designated initializer        [theCopy setItemId:[self.itemId copy]];    [theCopy setImage:[self.image copy]];    [theCopy setName:[self.name copy]];    [theCopy setSpicyLevel:[self.spicyLevel copy]];    [theCopy setRating:[self.rating copy]];    [theCopy setItemDescription:[self.itemDescription copy]];    [theCopy setWaitingTime:[self.waitingTime copy]];    [theCopy setReviewCount:[self.reviewCount copy]];    [theCopy setReviews:[self.reviews copy]];        return theCopy;}@end

具体使用:

RESTfulEngine.m

//根据dict得到MenuItem实例[[MenuItem alloc] initWithDictionary:obj]

- (RESTfulOperation *)fetchMenuItemsOnSucceeded:(ArrayBlock)succeedBlock onError:(ErrorBlock)errorBlock{        RESTfulOperation *op = (RESTfulOperation *)[self operationWithPath:MENU_ITEMS_URL];        [op onCompletion:^(MKNetworkOperation *completedOperation) {        //得到返回的JSON字符串        NSMutableDictionary *responseDictionary = [completedOperation responseJSON];        //得到字符串中的menuitems的子节点的内容        NSMutableArray *menuItemsJson = [responseDictionary objectForKey:@"menuitems"];                NSMutableArray *menuItems = [NSMutableArray array];                //遍历节点,        [menuItemsJson enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {            //然后将其中的key-value 通过 initWithDictionary 给类的属性赋值            [menuItems addObject:[[MenuItem alloc] initWithDictionary:obj]];        }];                succeedBlock(menuItems);    } onError:errorBlock];        [self enqueueOperation:op];    return op;}

Demo 下载地址:iHotelAPP

0 0
原创粉丝点击