过去,判断一个字典对象的合法性,采用了下面的方案。有一个很大的缺点就是,数据非法时,想要定位到哪个字段出了问题,这事并不轻松。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
+ (BOOL)isValidDic:(NSDictionary *)dic
{
if (![super isValidDic:dic]
|| !DIC_HAS_STRING(dic, SYNC_USER_UID)
|| !DIC_HAS_STRING(dic, SYNC_CONTENT)
|| !DIC_HAS_NUMBER(dic, SYNC_CREATE_TIME)
|| !DIC_HAS_ARRAY(dic, SYNC_COMMENTS)
|| !DIC_HAS_ARRAY(dic, SYNC_FAVORS)
|| !DIC_HAS_ARRAY(dic, SYNC_VISITORS)
|| !DIC_HAS_NUMBER(dic, SYNC_COMMENT_NUM)
|| !DIC_HAS_NUMBER(dic, SYNC_FAVOR_NUM)
|| !DIC_HAS_NUMBER(dic, SYNC_VISITOR_NUM)
|| !DIC_HAS_NUMBER(dic, SYNC_IS_HIDE_IN_SQUARE)
|| !DIC_HAS_NUMBER(dic, SYNC_FAVORED)
|| !DIC_HAS_ARRAY(dic, SYNC_PHOTOS)
|| ![UserBasicInfo isValidDic:dic[SYNC_USER_INFO]]
)
{
return NO;
}

return YES;
}
优化方案

这个思路不限于 Objective-C

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
+ (BOOL)isValidDic:(NSDictionary *)dic
{
NSDictionary *checkMap = @{@"super": ^{return [super isValidDic:dic];},
SYNC_USER_UID: ^{return DIC_HAS_STRING(dic, SYNC_USER_UID);},
SYNC_CONTENT: ^{return DIC_HAS_STRING(dic, SYNC_CONTENT);},
SYNC_CREATE_TIME: ^{return DIC_HAS_NUMBER(dic, SYNC_CREATE_TIME);},
SYNC_COMMENTS: ^{return DIC_HAS_ARRAY(dic, SYNC_COMMENTS);},
SYNC_FAVORS: ^{return DIC_HAS_ARRAY(dic, SYNC_FAVORS);},
SYNC_VISITORS: ^{return DIC_HAS_ARRAY(dic, SYNC_VISITORS);},
SYNC_COMMENT_NUM: ^{return DIC_HAS_NUMBER(dic, SYNC_COMMENT_NUM);},
SYNC_FAVOR_NUM: ^{return DIC_HAS_NUMBER(dic, SYNC_FAVOR_NUM);},
SYNC_VISITOR_NUM: ^{return DIC_HAS_NUMBER(dic, SYNC_VISITOR_NUM);},
SYNC_IS_HIDE_IN_SQUARE: ^{return DIC_HAS_NUMBER(dic, SYNC_IS_HIDE_IN_SQUARE);},
SYNC_FAVORED: ^{return DIC_HAS_NUMBER(dic, SYNC_FAVORED);},
SYNC_PHOTOS: ^{return DIC_HAS_ARRAY(dic, SYNC_PHOTOS);},
SYNC_USER_INFO: ^{return [UserBasicInfo isValidDic:dic[SYNC_USER_INFO]];}
};
for (NSString *key in [checkMap allKeys])
{
BOOL (^handler)() = checkMap[key];
BOOL ret = handler();
if(!ret)
{
CLog(@"%@ %@: invalid: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), key);
return NO;
}
}

return YES;
}