Mantle简介
Mantle
是github 的工程师们弄出来的东西,是iOS和Mac平台下基于Objective-C编写的一个简单高效的模型层框架。
Mantle能做什么
当我们从服务器获取数据,这些数据一般都为JSON
格式,我们常用的做法是将JSON
数据转为Model
对象,
然后我们就从Model
对象的属性里读取数据。
也许你已经体会到这时噩梦的开始,因为你每次都要用-initWithDictionarty:(NSDictionary *)dict
等类似
方法来初始化,把JSON
数据里的值一个一个的赋值给Model
对象的属性,是否有一种重复工作的感觉。
当你需要的某个数据在JSON字典数据里层次很深时,需要不断的使用[[obj objectForKey:@"key"] objectAtIndex:index] objectForKey:@""]...
,
这么长的代码简直让人崩溃。
这些还没完,如果服务器给你返回的数据并不是你所期望,例如你需要的是NSString
,但给你一个NSNumber
;
有时你需要NSDate
,却给了你NSString
。你不得不去做一些判断,写一些转换的代码。还有一种严重的情况,
由于服务器故障,给你返回了一个NSNull,如果你没有做一些判断处理,那么这时你的程序崩溃的几率很大。
Mantle可以轻松把JSON
数据、字典Dictionary
和模型Objective
之间的相互转换,支持自定义映射,
并且内置实现了NSCoding
和NSCoping
,大大简化归档操作。
使用介绍
首先你需要建立一个空工程,把Mantle
代码下载回来,拖进你的工程。我还是建议使用CocoaPos
来管理第三方库。大概浏览一下框架目录,如下图:
文件比较多,但我们常用到的就是MTLJSONAdapter
和MTLModle
。MTLModel
是一个抽象类,它帮我们做了很多工作。
我们要建的Model
类应该继承于它,此外你的继承类一定还要实现MTLJSONSerializing
协议。MTLJSONAdapter
则是
帮我们把JSON
数据绑定到Model
的属性里,当然,你不用担心会出现NSNull
的情况,因为转换后它会自动设置成nil
。
假设我们需要对象化的数据如下:
NSDictionary *response = @{
@"id" : @"1",
@"phone" : @"xxxxxxxx",
@"date" : @"2016-06-19",
@"goldNumber" : @2,
@"info":@{@"version":@"1.0"}
};
我们新建一个继承MTLModel
的类,叫做TestDataModel
。
#import <Mantle/Mantle.h>
@interface TestDataModel : MTLModel<MTLJSONSerializing>
@property (nonatomic, retain) NSString *memberID;
@property (nonatomic, retain) NSString *mobilePhone;
@property (nonatomic, retain) NSString *createDate;
@property (nonatomic, retain) NSNumber *goldNumber;
@property (nonatomic, retain) NSString *version;
@end
在TestDataModel.m
文件里,实现MTLJSONSerializing
协议里的+ (NSDictionary *)JSONKeyPathsByPropertyKey
方法。
@implementation TestDataModel
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
return @{
@"memberID" : @"id",//将JSON字典里id键对应的值,赋值给memberID属性
@"mobilePhone" : @"phone",
@"createDate" : @"date",
@"goldNumber" : @"goldNumber",
@"version": @"info.version"//这个点是什么意思呢,表示将info键对应的子字典里version键对应的值赋给version属性
};
}
@end
接下来我们将JSON
数据和Model
的属性进行绑定
TestDataModel *member = [MTLJSONAdapter modelOfClass:[TestDataModel class] fromJSONDictionary:response error:nil];
也许你会有个疑问,如果info键对应的数组,该如何实现呢?
{
code = 0x0000;
info = {
products = (
{
imageUrl = "http://www.sainsmart.com/media/imatic/adv/product/default/ad01.png";
link = "http://www.ebay.com/itm/Raspberry-Pi-3-Model-B-Basic-Starter-Complete-Ultimate-Accessory-Camera-Kit-/301931262954";
sku = "101-40-179";
},
{
imageUrl = "http://www.sainsmart.com/media/imatic/adv/product/default/ad04.png";
link = "http://www.ebay.com/itm/SainSmart-DSO238-2-8-TFT-Digital-Oscilloscope-Kit-DIY-parts-1Msps-Update-DSO138-/301934861076?ssPageName=STRK:MESE:IT";
sku = "101-10-148";
},
{
imageUrl = "http://www.sainsmart.com/media/imatic/adv/product/default/ad03.png";
link = "http://www.sainsmart.com/sainsmart-6-axis-control-palletizing-robot-arm-model-diy-w-arduino-controller-servos-diy.html";
sku = "20-011-405";
},
{
imageUrl = "http://www.sainsmart.com/media/imatic/adv/product/default/ad02.png";
link = "http://www.sainsmart.com/sainsmart-instabots-upright-rover-kit-pro-updated-2-wheel-self-balancing-robot-kit.html";
sku = "20-014-310";
}
);
version = 0;
};
result = 1;
}
假设我们现在需要处理上面的数据,在TestDataModel.h
我们新建如下代码:
@interface ProductInfo : MTLModel<MTLJSONSerializing>
@property (nonatomic, retain) NSString *imageUrl;
@property (nonatomic, retain) NSString *link;
@property (nonatomic, retain) NSString *sku;
@end
@interface Product : MTLModel<MTLJSONSerializing>
@property (nonatomic, assign) NSNumber *result;
@property (nonatomic, retain) NSString *code;
@property (nonatomic, retain) NSString *version;
@property (nonatomic, retain) ProductInfo *products;
@end
在TestDataModel.m
实现+ (NSDictionary *)JSONKeyPathsByPropertyKey
,
以及添加+ (NSValueTransformer *)xxxJSONTransformer
,xxx
就是根据你的属性名来写的。
@implementation Product
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
return @{@"code":@"code",
@"result":@"result",
@"version":@"info.version",
@"products":@"info.products"};
}
+ (NSValueTransformer *)productsJSONTransformer {
//return [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:[ProductInfo class]];
return [MTLJSONAdapter arrayTransformerWithModelClass:[ProductInfo class]];
}
@end
@implementation ProductInfo
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
return @{@"imageUrl":@"imageUrl",
@"link":@"link",
@"sku":@"sku"};
}
@end
一切准备就绪,现在我们来进行绑定
NSError *error;
Product *model = [MTLJSONAdapter modelOfClass:[Product class] fromJSONDictionary:你的数据源变量 error:&error];
NSArray *array = model.products;
for (ProductInfo *info in array) {
NSLog(@"%@", info.imageUrl);
}