NSArray containsObject判断失效:类型不匹配问题排查求助
排查
containsObject:匹配失败:NSNumber与NSString类型不匹配问题 核心原因
containsObject:内部通过isEqual:方法判断对象是否相等,NSNumber和NSString属于不同类型,即使值完全相同,isEqual:也会直接返回NO,导致匹配失败。比如@"123"和@123调用isEqual:永远不会返回YES。
为什么swagger生成的模型会出现类型不符?
swagger-codegen完全依据swagger文档生成代码,如果后端实际返回的JSON数据类型和swagger文档定义不一致,就会出现模型声明类型与实际存储类型不匹配的情况:
- 假设swagger文档中
apiArray字段定义为integer类型,生成的模型会声明为NSArray<NSNumber*>*; - 但如果后端实际返回的是字符串类型的数值(比如
["1", "2"]而非[1,2]),JSON解析库(无论原生NSJSONSerialization还是第三方库)都会按JSON原生类型解析,将元素存为NSString,而非自动转换为NSNumber。
排查步骤
- 抓包验证后端返回:查看接口实际返回的JSON,确认
apiArray的元素是字符串还是数字类型; - 核对swagger文档定义:检查swagger spec中该字段的类型是否与后端实际返回一致;
- 查看生成的模型解析逻辑:打开swagger生成的模型
.m文件,确认字段解析时是否有类型转换逻辑——大部分默认生成的模板不会自动做跨类型转换。
解决办法
临时修复(不修改模型)
在调用containsObject:前统一类型:
- 将
apiArray的元素转为NSNumber:
NSMutableArray *convertedArray = [NSMutableArray array]; for (id obj in apiArray) { if ([obj isKindOfClass:[NSString class]]) { [convertedArray addObject:@([obj integerValue])]; } else { [convertedArray addObject:obj]; } } BOOL contains = [convertedArray containsObject:localObject];
- 或者将
localObject转为NSString:
NSString *localString = [localObject stringValue]; BOOL contains = [apiArray containsObject:localString];
长期修复(从根源解决)
- 修正swagger文档,让字段类型与后端实际返回完全一致,重新生成模型;
- 若后端无法修改返回类型,可自定义swagger-codegen模板,添加类型转换逻辑(比如在解析时自动将字符串转为NSNumber)。
内容的提问来源于stack exchange,提问作者Vincenzo
相关产品推荐
相关产品推荐

