iOS开发NSInvalidArgumentException报错:未识别选择器发送至NSTaggedPointerString实例
解决
-[NSTaggedPointerString objectForKey:]崩溃问题 这个崩溃的原因非常清晰:你尝试对一个字符串对象调用objectForKey:方法,但NSString(这里是NSTaggedPointerString,NSString的一种内存优化实现)根本没有这个方法,所以触发了NSInvalidArgumentException。
问题出在哪?
从你的代码和JSON示例来看,你预期defaultDict[@"data"]是一个包含字典的数组,但实际运行时,mobile变量被赋值成了字符串。可能的场景有两种:
- 服务器返回的JSON格式和你预期的不一致——比如某个异常情况下,
data字段的值是一个错误提示字符串,而非数组; - JSON解析过程中出了问题,但你用
error:nil忽略了解析错误,导致错误的对象被赋值给了mobile。
修复方案
我给你一套更健壮的代码,包含错误捕获和类型检查,彻底避免这类崩溃:
if ([method isEqualToString:@"getmobiledata"]) { // 1. 捕获JSON解析错误,再也不要忽略error参数! NSError *jsonParseError = nil; id jsonRoot = [NSJSONSerialization JSONObjectWithData:[data dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&jsonParseError]; if (jsonParseError) { NSLog(@"JSON解析失败: %@", jsonParseError.localizedDescription); return; // 解析失败直接退出,避免后续错误 } // 2. 检查根节点是否是字典 if (![jsonRoot isKindOfClass:[NSDictionary class]]) { NSLog(@"服务器返回的JSON根节点不是字典,类型为: %@", [jsonRoot class]); return; } defaultDict = [[NSMutableDictionary alloc] initWithDictionary:jsonRoot]; mobile = defaultDict[@"data"]; // 3. 关键:检查data字段的类型是否符合预期 if ([mobile isKindOfClass:[NSArray class]]) { // 类型正确,遍历数组处理每个条目 for (NSDictionary *mobileItem in mobile) { // 这里也可以对每个字段做类型检查,更严谨 NSString *itemId = mobileItem[@"id"]; NSString *package = mobileItem[@"package"]; NSString *rate = mobileItem[@"rate"]; NSString *type = mobileItem[@"type"]; NSLog(@"获取到套餐: ID=%@, 流量=%@, 价格=%@, 运营商=%@", itemId, package, rate, type); // 这里把数据存储到变量或模型里 } } else { // 类型不符,记录日志并处理错误 NSLog(@"预期data是数组,但实际得到: %@ (类型: %@)", mobile, [mobile class]); // 比如弹出提示告诉用户数据加载失败 } }
额外建议
- 永远不要忽略错误参数:
NSJSONSerialization的error能帮你快速定位格式错误、编码问题等; - 强制类型检查:服务器返回的数据随时可能变动,每次使用JSON字段前都验证类型,是避免这类崩溃的核心;
- 可以临时打印
mobile的类型和值,快速排查问题:NSLog(@"mobile的值: %@, 类型: %@", mobile, [mobile class]);
内容的提问来源于stack exchange,提问作者Mr david alan
相关产品推荐
相关产品推荐

