关于NSObject的setValue forKey的一个小tip
这两天重构项目的认证接口,接口的大概功能是,要根据每个字段的值去判断
每个认证的状态,接口的返回值大概是这样的。。。。。。
{
code = 0;
data = {
button = 1;
contact = 1;
credential = 0;
"credit_indicator" = 243;
housingfund = 0;
idcard = 1;
information = 0;
isp = 0;
jingdong = 0;
"loan_history" = 0;
report = 0;
taobao = 0;
time = "2017-08-01T11:18:52.000+08:00";
zhima = 1;
"zhima_certifications" = 1;
};
"reset_data" = (
);
"update_prompt" = (
{
identity = 0;
},
{
contact = 1;
}
);
}
我来解释一下这个返回数据,data里的0和1的那些字段每个对应一个认证,1表示已认证,0为未认证。
reset_data和update_prompt都是数组,数组里的元素一个字典,字典里的字段对应一个认证。
reset_data里的字典如果包含某个字段,则该认证状态为已过期。
update_prompt里的字典如果包含某个字段,并且值为1,则该认证状态为可更新,例如contact,否则为已更新,例如identity
这个逻辑是不是很奇葩。。。其实完全可以用"字段"=1或者2、3这样表示
每个认证的状态,例如:1未认证2已认证3已过期4可更新5已更新
(别问我接口后台谁写的,我也很绝望啊)
以前的数据解析是这样的。。。
if (dict[@"carrier"]) {
if ([dict[@"carrier"] intValue] == 1) {
[defaults setObject:@"3" forKey:@"SERVICEShine"];
}else{
[defaults setObject:@"4" forKey:@"SERVICEShine"];
}
}else if (dict[@"taobao"]) {
if ([dict[@"taobao"] intValue] == 1) {
[defaults setObject:@"3" forKey:@"TBShine"];
}else{
[defaults setObject:@"4" forKey:@"TBShine"];
}
} ....此处省略无数个if else
单单一个数据解析写了近200行,然后还在多处地方用到。。。对于有技术追求的我们,怎么能这么干呢?
果断重构之,方案如下:
新建一个model类,创建一个枚举类型,表示认证的每种状态
typedefNS_ENUM(NSInteger, NAAuthenticationState) {
NAAuthenticationStateNot =0,// 未认证
NAAuthenticationStateAlready,// 已认证
NAAuthenticationStateOverdue,// 已过期
NAAuthenticationStateCanUpdate,// 可更新
NAAuthenticationStateAlreadyUpdate// 已更新
};
添加data中的每个key作为属性,此类有3个方法:
-
单例
+ (instancetype)sharedModel;
-
获取所有属性名
+ (NSArray*)getAllProperties;
-
然后是解析方法
+ (void)analysisAuthentication:(NSDictionary*)returnValue;
解析方法的实现具体也分3步,因为坑爹的返回数据格式。
返回数据分三部分,为了方便理解,我们命名为dataDic、resetArr、updateArr,数据类型应该一目了然吧。
1. dataDic
首先利用第三方库YYModel对dataDic字典里的数据进行model转换
[model yy_modelSetWithJSON:dataDic];
这里刚好0代表未认证,1代表已认证,所以这一句就够了。
2. resetArr
然后遍历数组resetArr,再遍历里面的字典进行赋值,由于这里的数据value还都是0,我们需要的值是NAAuthenticationStateOverdue
,也即是2,而且有个别key居然跟上一步的命名不一样。。。所以不能直接用yymodel赋值了。
我们选择在遍历字典时,先把不一样的key单独找出来赋值成NAAuthenticationStateOverdue
,然后其他的利用setValueforKey进行赋值
重点来了
setValueforKey的value必须为id类型,而我们的属性是枚举类型,也即是NSInteger,这样用会报错,怎么办呢?
id propertyValue = [[[NSNumberFormatter alloc] init] numberFromString:@"2"];
这样我们再用setValueforKey就没问题了,完美~
3. updateArr
跟第二步类似
到此解析完成,这样我们就算是在很多地方用到,只需要引入此model,调用解析方法即可,简洁美观~
哦,对了还有一点,至于为什么不像旧的那样,用NSUserDefaults
保存本地,我认为是没有必要的。
因为这些数据在用到的时候,都会提前请求更新一下,本地保存完全没有意义,故用单例保存足以。
附上Demo ,如果您感觉有一点点用的话,请帮忙star一下,谢谢啦~
网友评论