iOS应用崩溃:[__NSCFNumber rangeOfCharacterFromSet:]选择器无法识别求助
解决反向地理编码崩溃问题:
[__NSCFNumber rangeOfCharacterFromSet:]: unrecognized selector 从你的报错信息和代码来看,崩溃的核心原因是某个NSNumber对象被当成NSString来调用方法了,结合代码细节和iOS反向地理编码的坑,我整理出以下修复方案:
一、崩溃根源分析
报错显示向NSNumber发送了NSString的rangeOfCharacterFromSet:方法,结合你的代码,大概率是两个问题叠加:
- 依赖
CLPlacemark.addressDictionary[@"FormattedAddressLines"]获取地址数组,这个内部字典的结构在不同iOS版本/地区可能不稳定,返回值可能不是预期的NSArray(甚至出现NSNumber类型),导致后续字符串拼接时触发类型错误。 - 反向地理编码的回调是在后台线程执行的,你直接在回调里更新UI控件(
_usrtAddressLbl.text等),违反了iOS UI操作必须在主线程的规则,这也可能引发不可预测的崩溃。
二、具体修复步骤
1. 先确保经纬度的合法性
先对字典里的经纬度值做类型校验,避免无效值传入:
-(void)getMerchantAddress:(NSDictionary *)dict { // 安全解析纬度 id latObj = dict[@"user_lat"]; double lata = 0.0; if ([latObj isKindOfClass:[NSNumber class]]) { lata = [(NSNumber *)latObj doubleValue]; } else if ([latObj isKindOfClass:[NSString class]]) { lata = [(NSString *)latObj doubleValue]; } // 安全解析经度 id longObj = dict[@"user_long"]; double longa = 0.0; if ([longObj isKindOfClass:[NSNumber class]]) { longa = [(NSNumber *)longObj doubleValue]; } else if ([longObj isKindOfClass:[NSString class]]) { longa = [(NSString *)longObj doubleValue]; } // 校验经纬度范围是否合法(纬度±90,经度±180) if (lata < -90 || lata > 90 || longa < -180 || longa > 180) { NSLog(@"无效的经纬度值"); return; } // 后续地理编码代码... }
2. 替换地址拼接逻辑,避免依赖内部字典
不要用addressDictionary的私有键值,改用CLPlacemark公开的属性来构建地址,这是苹果官方推荐的稳定方式:
CLLocation *locationAtual = [[CLLocation alloc] initWithLatitude:lata longitude:longa]; CLGeocoder *geocoder = [[CLGeocoder alloc] init]; [geocoder reverseGeocodeLocation:locationAtual completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) { // 先处理错误 if (error) { NSLog(@"反向地理编码失败:%@", error.localizedDescription); return; } if (placemarks.count == 0) { NSLog(@"未找到匹配的地址"); return; } CLPlacemark *placemark = placemarks.firstObject; NSMutableString *addressString = [NSMutableString string]; // 按地址层级拼接(可根据需求调整顺序) if (placemark.thoroughfare) [addressString appendString:placemark.thoroughfare]; if (placemark.subThoroughfare && addressString.length > 0) [addressString appendFormat:@", %@", placemark.subThoroughfare]; if (placemark.locality && addressString.length > 0) [addressString appendFormat:@", %@", placemark.locality]; if (placemark.administrativeArea && addressString.length > 0) [addressString appendFormat:@", %@", placemark.administrativeArea]; if (placemark.postalCode && addressString.length > 0) [addressString appendFormat:@", %@", placemark.postalCode]; if (placemark.country && addressString.length > 0) [addressString appendFormat:@", %@", placemark.country]; // 必须回到主线程更新UI! dispatch_async(dispatch_get_main_queue(), ^{ _usrtAddressLbl.text = addressString; _userAddressLbl.text = addressString; }); }];
3. 额外检查点
- 确认你的
_usrtAddressLbl和_userAddressLbl是正确关联的UILabelIBOutlet,没有误连到其他类型的对象。 - 确保设备有网络权限(反向地理编码需要联网),并且在Info.plist中配置了位置权限(
NSLocationWhenInUseUsageDescription等)。
内容的提问来源于stack exchange,提问作者V-Dev
相关产品推荐
相关产品推荐

