iOS Charts折线图捏合缩放报错:Double无法转为Int(无限或NaN)
iOS Charts折线图捏合缩放崩溃问题解决方案
嘿,我之前碰过iOS Charts库类似的缩放崩溃坑,咱们来一步步排查解决这个问题~
你遇到的Fatal error: Double value cannot be converted to Int because it is either infinite or NaN错误,本质是捏合缩放时,AxisRendererBase在计算坐标轴刻度、坐标位置时,生成了非法的Double值(NaN/无穷大),然后强制转Int时触发崩溃。常见的触发场景是过度缩放导致坐标轴范围计算异常,或者数据/复用状态有问题,下面是针对性的解决方案:
1. 先限制折线图的缩放范围(最快速的临时修复)
过度缩放是最容易触发这个问题的原因——当你把折线图缩到极致时,坐标轴的min/max值可能会变得异常,甚至出现除以0的计算。给折线图设置最大缩放比例,避免用户缩到离谱的程度:
// 在configureCell或者图表初始化时设置 cell.lineChartView.scaleXEnabled = true cell.lineChartView.scaleYEnabled = true // 根据你的数据调整最大缩放值,比如X轴最多放大5倍 cell.lineChartView.viewPortHandler.setMaximumScaleX(5.0) cell.lineChartView.viewPortHandler.setMaximumScaleY(5.0)
2. 检查并清洗数据源
如果你的折线图数据里本身存在NaN、无穷大的数值,缩放时计算坐标轴范围会直接生成非法值。在配置数据前先过滤无效数据:
// 假设dataEntries是你的原始数据条目数组 let validEntries = dataEntries.filter { entry in !entry.y.isNaN && !entry.y.isInfinite } // 用清洗后的有效数据生成数据集 let lineDataSet = LineChartDataSet(entries: validEntries, label: "折线图数据") let lineData = LineChartData(dataSet: lineDataSet) cell.lineChartView.data = lineData
3. 自定义安全的坐标轴渲染器
如果上面的方法还解决不了,可以重写AxisRenderer的方法,在计算坐标轴数值前先判断合法性,避免崩溃:
// 自定义X轴渲染器,处理非法数值 class SafeXAxisRenderer: XAxisRenderer { override func computeAxisValues(min: Double, max: Double) { // 先判断min和max是否合法,不合法就用默认范围 guard !min.isNaN, !max.isNaN, !min.isInfinite, !max.isInfinite else { super.computeAxisValues(min: 0, max: 1) return } super.computeAxisValues(min: min, max: max) } } // 同理可以自定义Y轴渲染器 class SafeYAxisRenderer: YAxisRenderer { override func computeAxisValues(min: Double, max: Double) { guard !min.isNaN, !max.isNaN, !min.isInfinite, !max.isInfinite else { super.computeAxisValues(min: 0, max: 1) return } super.computeAxisValues(min: min, max: max) } }
然后在配置图表时替换默认渲染器:
// 给折线图设置自定义渲染器 cell.lineChartView.xAxis.renderer = SafeXAxisRenderer( viewPortHandler: cell.lineChartView.viewPortHandler, xAxis: cell.lineChartView.xAxis, transformer: cell.lineChartView.getTransformer(forAxis: .left) ) cell.lineChartView.leftAxis.renderer = SafeYAxisRenderer( viewPortHandler: cell.lineChartView.viewPortHandler, yAxis: cell.lineChartView.leftAxis, transformer: cell.lineChartView.getTransformer(forAxis: .left) )
4. 排查TableView单元格复用的状态问题
因为图表是放在TableView单元格里的,复用单元格时如果没有重置图表的缩放状态,可能导致旧的缩放状态和新数据冲突,触发计算异常。在configureCell方法里,复用单元格时先重置图表状态:
func configureCell(_ cell: ChartTableViewCell, for indexPath: IndexPath) { // 重置图表的缩放和数据状态 cell.lineChartView.clear() cell.lineChartView.viewPortHandler.resetZoom() cell.lineChartView.data = nil // 然后再配置当前单元格的图表数据 // ... 你的数据配置代码 }
建议先从第1、2步开始排查,这两个是最常见的触发原因,大部分情况下都能解决问题。如果还是不行,再尝试自定义渲染器或者检查复用逻辑~
内容的提问来源于stack exchange,提问作者atalayasa
相关产品推荐
相关产品推荐

