iOS開發(fā)中,網(wǎng)絡(luò)請(qǐng)求得到j(luò)son轉(zhuǎn)化為字典聚蝶,然后字典轉(zhuǎn)化為模型杰妓,這是很普遍要做的事。成型的第三方框架也有很多碘勉,前段時(shí)間比較火的YYKit中的YYMoel對(duì)各大這方面的框架包括JsonModel巷挥,MjExtension等效率都有所對(duì)比。但是授之以魚不如授之以漁验靡,有時(shí)候我們僅僅想要的就是字典轉(zhuǎn)模型而已句各,簡(jiǎn)單,可控晴叨,可自定義凿宾。今天,小編我提供了一下自己的解決方案兼蕊。
先來一波思路分析初厚。
后臺(tái)返回的數(shù)據(jù)json(xml很少人在用了吧)的類型的數(shù)據(jù)格式有對(duì)象和數(shù)組
, 字符串
,數(shù)字
,布爾
孙技,null
产禾,使用系統(tǒng)自帶的NSJSONSerialization
得到字典,會(huì)將對(duì)象轉(zhuǎn)化為NSDictionary對(duì)象牵啦,數(shù)組轉(zhuǎn)化為NSArray對(duì)象亚情,字符串轉(zhuǎn)化為NSString對(duì)象,數(shù)字和布爾類型轉(zhuǎn)化為NSValue對(duì)象或者子類NSNumber對(duì)象哈雏,null轉(zhuǎn)化為NSNull對(duì)象楞件。json中的null這個(gè)就需要小心了。java的后臺(tái)程序可能是直接將model轉(zhuǎn)化為json裳瘪,當(dāng)對(duì)象沒初始化為null時(shí)土浸,json就會(huì)出現(xiàn)null,而不是應(yīng)該有的{}彭羹。null會(huì)轉(zhuǎn)化為NSNull黄伊,但是我們認(rèn)為他是對(duì)象類型,轉(zhuǎn)化為了NSDictionary對(duì)象派殷,然后調(diào)用了objectForkey还最,就會(huì)報(bào)unRecognized selector exception
使程序崩潰墓阀。關(guān)于這點(diǎn),我曾經(jīng)和做后臺(tái)的同事爭(zhēng)吵過拓轻,說:你既然定義json中某key的值是對(duì)象類型斯撮,為空你也要傳“{}”啊({}會(huì)轉(zhuǎn)化為空字典類型),為什么傳null悦即。他們爭(zhēng)論到:從數(shù)據(jù)庫(kù)中查不到吮成,就沒必要初始化model對(duì)象,轉(zhuǎn)化為json也就會(huì)為null辜梳。我直接無語了粱甫。
直接上代碼吧。注釋還是蠻清晰的作瞄,記得不要忘記把那兩個(gè)“安全設(shè)置”加上茶宵,不然,碰到手誤宗挥,忘記定義的屬性乌庶,程序又該崩潰了。setNilValueForKey:
這個(gè)不常用契耿,是定義assign類型的屬性給它set nil才會(huì)觸發(fā)瞒大。加上也不多。
- (instancetype)initWithDic:(NSDictionary*)dic
{
if (!dic || ![dic isKindOfClass:[NSDictionary class]]) {
return nil;
}
if (self = [super init]) {
for (NSString *key in [dic allKeys]) {
id value = dic[key];
//1.處理對(duì)象類型和數(shù)組類型
if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
[self setValue:value forKeyPath:key];
}
//2.處理空類型:防止出現(xiàn)unRecognized selector exception
else if ([value isKindOfClass:[NSNull class]]) {
// [self setValue:nil forKey:key];
}
//3.處理其他類型:包括數(shù)字搪桂,字符串透敌,布爾,全部使用NSString來處理
else{
[self setValue:[NSString stringWithFormat:@"%@",value] forKeyPath:key];
}
}
}
return self;
}
#pragma mark KVC 安全設(shè)置
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
NSLog(@"%s",__func__);
}
- (void)setNilValueForKey:(NSString *)key
{
NSLog(@"%s",__func__);
}
JSONModel有一個(gè)好處踢械,就是我們?cè)趐o或者log打印model對(duì)象的時(shí)候回直接展示他的屬性值酗电。其實(shí)就是重寫description
方法而已。我們也來一波自定義:
#pragma mark po或者打印時(shí)打出內(nèi)部信息
-(NSString *)description
{
NSMutableString* text = [NSMutableString stringWithFormat:@"<%@> \n", [self class]];
NSArray* properties = [self filterPropertys];
[properties enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString* key = (NSString*)obj;
id value = [self valueForKey:key];
NSString* valueDescription = (value)?[value description]:@"(null)";
if ( ![value respondsToSelector:@selector(count)] && [valueDescription length]>60 ) {
valueDescription = [NSString stringWithFormat:@"%@...", [valueDescription substringToIndex:59]];
}
valueDescription = [valueDescription stringByReplacingOccurrencesOfString:@"\n" withString:@"\n "];
[text appendFormat:@" [%@]: %@\n", key, valueDescription];
}];
[text appendFormat:@"</%@>", [self class]];;
return text;
}
方法調(diào)用了[self filterPropertys]
獲本類的所有屬性内列。這個(gè)用到了所謂的“高大上”的objc的runtime中方法了撵术。先來一波包含頭文件#import <objc/runtime.h>
。然后在上代碼话瞧。
#pragma mark 獲取一個(gè)類的屬性列表
- (NSArray *)filterPropertys
{
NSMutableArray* props = [NSMutableArray array];
unsigned int count;
objc_property_t *properties = class_copyPropertyList([self class], &count);
for(int i = 0; i < count; i++){
objc_property_t property = properties[i];
const char* char_f =property_getName(property);
NSString *propertyName = [NSString stringWithUTF8String:char_f];
[props addObject:propertyName];
// NSLog(@"name:%s",property_getName(property));
// NSLog(@"attributes:%s",property_getAttributes(property));
}
free(properties);
return props;
}
最后嫩与。字典轉(zhuǎn)模型,你是轉(zhuǎn)了移稳,那模型轉(zhuǎn)字典呢蕴纳?作為一個(gè)實(shí)用主義的程序員,如果不是有需求用到了个粱,我才不去想這個(gè)的,多燒腦子啊??翻翩。開發(fā)時(shí)都许,有時(shí)候需要提交數(shù)據(jù)給后臺(tái)稻薇,由于網(wǎng)絡(luò)請(qǐng)求的封裝,只需要傳一個(gè)字典對(duì)象過去就行胶征。如果需要把一個(gè)model對(duì)象所有屬性都作為參數(shù)提交塞椎,那么就需要吧model轉(zhuǎn)化為字典類型。方法如下:
#pragma mark 模型中的字符串類型的屬性轉(zhuǎn)化為字典
-(NSDictionary*)modelStringPropertiesToDictionary
{
NSArray* properties = [self filterPropertys];
NSMutableDictionary* dic = [NSMutableDictionary dictionary];
[properties enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString* key = (NSString*)obj;
id value = [self valueForKey:key];
if ([value isKindOfClass:[NSString class]]) {
NSString* va = (NSString*)value;
if (va.length > 0) {
[dic setObject:value forKey:key];
}
}
}];
return dic;
}
將以上代碼封裝一個(gè)BaseModel類睛低,所有model類繼承它案狠。
以上只是根據(jù)自己的所學(xué)加以運(yùn)用而已,一千個(gè)讀者就有一千個(gè)哈姆雷特钱雷。好多東西不是沒法解決骂铁,只是暫時(shí)不知道解決的辦法而已。這篇文章是自己的所學(xué)的一個(gè)總結(jié)罩抗,希望對(duì)讀者有所幫助拉庵。