如何为字符串创建的NSNumber数组实现无崩溃正确排序
崩溃问题根因
- 代码里用
NSNumber(nonretainedObject:)生成y对象的逻辑完全走偏了:这个初始化器本来是用来把对象指针包装成NSValue的,从设计上就不是存数值的,最后生成的y在运行时的真实类型是NSValue,根本不是NSNumber。 - 因为Swift和OC的桥接层在这种类型不匹配的场景下不做编译期拦截,你可以把这个NSValue实例硬塞进声明成
Array<NSNumber>的数组里,但真跑到排序环节调用只有NSNumber才有的intValue方法时,直接就会因为找不到方法崩掉。 - 就算所有元素都是真的NSNumber,手动取
intValue比较的写法也有隐患:示例里20亿量级的数字在32位环境下本来就超出int的取值范围,很容易出现值截断、比较结果不对的问题。
稳定可落地的修复方案
- 先把字符串转NSNumber的错误逻辑改对,彻底删掉
nonretainedObject的相关调用,走标准转换流程生成真正的NSNumber实例,参考写法:
let targetStr = "2056787657" // 先处理字符串转数字失败的边界,比如内容是字母、数值超出范围等情况 guard let intVal = Int(targetStr) else { return } let y = NSNumber(value: intVal)
- 把排序逻辑改得更健壮,加上类型校验兜底,同时用NSNumber自带的比较方法替代手动拆值比较,既防崩溃又避溢出,参考排序代码:
theArray.sort { a, b in // 先校验异常的非NSNumber实例 guard let numA = a as? NSNumber, let numB = b as? NSNumber else { // 按业务规则定异常实例的排序优先级,比如统一排在最后 return false } // 原生compare方法自动适配不同数值类型,没有手动拆值的溢出风险 return numA.compare(numB) == .orderedAscending }
- 如果有存量代码没法直接修改,没法保证数组元素全是标准NSNumber,可以在数组入库的统一入口做类型清洗,把混进来的NSValue实例按业务规则转成正确的NSNumber,避免异常实例流到排序环节才崩。
内容的提问来源于stack exchange,提问作者Piepants
相关产品推荐
相关产品推荐

