Browse Source

close #3659: fix index out of bounds issue when using stacked bar chart

Pierre-Marc Airoldi 6 years ago
parent
commit
b03cf16ec4

+ 1 - 1
Source/Charts/Data/Implementations/Standard/BarChartDataSet.swift

@@ -133,7 +133,7 @@ open class BarChartDataSet: BarLineScatterCandleBubbleChartDataSet, IBarChartDat
     }
     
     /// array of labels used to describe the different values of the stacked bars
-    open var stackLabels: [String] = ["Stack"]
+    open var stackLabels: [String] = []
     
     // MARK: - Styling functions and accessors
     

+ 14 - 2
Source/Charts/Renderers/BarChartRenderer.swift

@@ -806,7 +806,15 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer
 
         if dataSet.isStacked, let vals = e.yValues
         {
-            let stackLabel = dataSet.stackLabels[idx % stackSize]
+            let labelCount = min(dataSet.colors.count, stackSize)
+
+            let stackLabel: String?
+            if (dataSet.stackLabels.count > 0 && labelCount > 0) {
+                let labelIndex = idx % labelCount
+                stackLabel = dataSet.stackLabels.indices.contains(labelIndex) ? dataSet.stackLabels[labelIndex] : nil
+            } else {
+                stackLabel = nil
+            }
 
             elementValueText = dataSet.valueFormatter?.stringForValue(
                 vals[idx % stackSize],
@@ -814,7 +822,11 @@ open class BarChartRenderer: BarLineScatterCandleBubbleRenderer
                 dataSetIndex: dataSetIndex,
                 viewPortHandler: viewPortHandler) ?? "\(e.y)"
 
-            elementValueText = stackLabel + " \(elementValueText)"
+            if let stackLabel = stackLabel {
+                elementValueText = stackLabel + " \(elementValueText)"
+            } else {
+                elementValueText = "\(elementValueText)"
+            }
         }
 
         let dataSetCount = dataProvider.barData?.dataSetCount ?? -1

+ 12 - 3
Source/Charts/Renderers/LegendRenderer.swift

@@ -52,12 +52,21 @@ open class LegendRenderer: Renderer
                 {
                     let bds = dataSet as! IBarChartDataSet
                     var sLabels = bds.stackLabels
-                    
-                    for j in 0..<min(clrs.count, bds.stackSize)
+                    let minEntries = min(clrs.count, bds.stackSize)
+
+                    for j in 0..<minEntries
                     {
+                        let label: String?
+                        if (sLabels.count > 0 && minEntries > 0) {
+                            let labelIndex = j % minEntries
+                            label = sLabels.indices.contains(labelIndex) ? sLabels[labelIndex] : nil
+                        } else {
+                            label = nil
+                        }
+
                         entries.append(
                             LegendEntry(
-                                label: sLabels[j % sLabels.count],
+                                label: label,
                                 form: dataSet.form,
                                 formSize: dataSet.formSize,
                                 formLineWidth: dataSet.formLineWidth,