RestKit是一个主要用于iOS上网络通信的开源框架,除了发送请求与接受响应这些基本功能外,还附带coredata,以及将远程JSON映射为本地对象的功能。目前版本0.9.3,coredata还不是很稳定,他的coredata的demo页面在4.3.3实机下直接导致程序crash,但是其JSON映射为本地对象的功能是十分强大的。
首先,RestKit要求我们在客户端定义一个Model类,用于存储数据和处理业务逻辑。远程JSON中各键将直接映射为Model中各成员变量。对应每一个模型都要定义一个对应的Model类,这是强制的。
强制定义模型带来的好处是我们只需要写一次字典中的key,不再会因为字典的key拼错导致程序crash了。
RestKit使用起来省时省力,但是思维方式和ASIHTTP差异不小,以下举一例说明。
1、
假设服务器上的JSON数据如下:
{
"id": 1234,
"name": "Personal Checking",
"balance": 5013.26,
"transactions": [
{"id": 1, "payee": "Joe Blow", "amount": 50.16},
{"id": 2, "payee": "Grocery Store", "amount": 200.15},
{"id": 3, "payee": "John Doe", "amount": 325.00},
{"id": 4, "payee": "Grocery Store", "amount": 25.15}]
}
我们用来存储此JSON的对象的类名为SimpleAccount,其中包含六个成员:
_accountID用来对应JSON的id;
_name对应JSON的name;
_balance对应JSON的balance;
_transactionCount对应JSON的transactions数组中元素的数量;
_averageTransactionAmount对应JSON里transactions各元素的amount值的平均数;
_distinctPayees是将JSON里transactions中各元素的payee的值取出来后拼接而成的数组。
首先在Model的.h里定义好我们的数据成员,在.m里写好synthesize:
@interface SimpleAccount : NSObject {
NSNumber* _accountID;
NSString* _name;
NSNumber* _balance;
NSNumber* _transactionsCount;
NSNumber* _averageTransactionAmount;
NSArray* _distinctPayees;
}
@property (nonatomic, retain) NSNumber* accountID;
@property (nonatomic, retain) NSString* name;
@property (nonatomic, retain) NSNumber* balance;
@property (nonatomic, retain) NSNumber* transactionsCount;
@property (nonatomic, retain) NSNumber* averageTransactionAmount;
@property (nonatomic, retain) NSArray* distinctPayees;
@end
@implementation SimpleAccount
@synthesize accountID = _accountID;
@synthesize name = _name;
@synthesize balance = _balance;
@synthesize transactionsCount = _transactionsCount;
@synthesize averageTransactionAmount = _averageTransactionAmount;
@synthesize distinctPayees = _distinctPayees;
@end
2、
在恰当的时机(比如viewDidAppear中)做JSON键到Model成员变量的映射,然后开始请求数据。
@”id”,@”accountID”,把本Model中的accountID属性映射为JSON的id键对应的值;name和balance属性同理。
@”transactions.@count”,@transactionsCount”,取JSON中transactions数组的元素数。
@”transactions.@avg.amount”,@averageTransactionAmount”,取JSON中transactions的各元素的amount的值的平均数。
@”transactions.@distinctUnionOfObjects.payee”,@”distinctPayees”,将JSON里transactions中各元素的payee的值取出来后拼接而成的数组。
@”transactions.@avg.amount”这种写法比较诡异,可以理解成调用transactions对象的avg方法,传入参数是amount。
代码如下
RKObjectMapping* mapping = [RKObjectMapping mappingForClass:[SimpleAccount class]];
[mapping mapKeyPathsToAttributes:
@"id", @"accountID",
@"name", @"name",
@"balance", @"balance",
@"transactions.@count", @"transactionsCount",
@"transactions.@avg.amount", @"averageTransactionAmount",
@"transactions.@distinctUnionOfObjects.payee", @"distinctPayees", nil];
3、
定义好映射之后,就可以开始向服务器请求数据了。
[RKObjectManager sharedManager]返回一个单件的RKObjectManager。在初始化时向里面存入服务器的URL;
loadObjectResourcePath指定需要请求的JSON数据在服务器中的相对路径(服务器地址已经储存在RKObjectManage里,所以无需在此指定);
objectClass指定映射成的对象的类;
delegate指定接受回调的对象,在请求完成时,此对象的- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects会被调用。
- (void)workWithKVC {
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:@"/accounts.json" objectClass:[SimpleAccount class] delegate:self];
}
4、
最后是回调方法,若收到的JSON根为数组,则返回数组。根不是数组,则返回一个count为1的数组,所以回调收到的objects是NSArray*类型的。
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {
SimpleAccount* account = [objects objectAtIndex:0];
// Will output "The count is 4"
NSLog(@"The count is %@", [account transactionsCount]);
// Will output "The average transaction amount is 150.115"
NSLog(@"The average transaction amount is %@", [account averageTransactionAmount]);
// Will output "The distinct list of payees is: Joe Blow, Grocery Store, John Doe"
NSLog(@"The distinct list of payees is: %@", [[account distinctPayees] componentsJoinedByString:@", "]);
}
参考资料http://mobile.tutsplus.com/tutorials/iphone/advanced-restkit-development_iphone-sdk/
以上
–OpenThread