I have a pie chart that displays data added to it It looks like this:
class HomeViewController: UIViewController {
var pieChart = PieChartView()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
pieChart.delegate = self
self.setChart()
}
func setChart() {
var entries: [ChartDataEntry] = []
for entry in 0..<(self.cellArr.count) {
if self.cellArr.count > 0 {
let dataEntry = PieChartDataEntry(value: Double(self.cellArr[entry].amount), label: String(self.cellArr[entry].type))
entries.append(dataEntry)
}
}
updateSorting(values: entries)
}
func updateSorting(values: [ChartDataEntry]){
let dataSet = PieChartDataSet(entries: values, label: "")
let data = PieChartData(dataSets: [dataSet])
dataSet.colors = ChartColorTemplates.colorful()
pieChart.data = data
pieChart.notifyDataSetChanged()
}
}
The problem is in the entries variable, which is located in the setChart function. I need to work with it outside the function, but if I put it in a class -
class HomeViewController: UIViewController {
var pieChart = PieChartView()
var entries: [ChartDataEntry] = [] // <------------ !!!
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
pieChart.delegate = self
self.setChart()
}
}
Then the chart will start displaying extra values
An illustrative example:
enter image description here enter image description here
In the first screenshot, entries is in a function, in the second it is already behind it
I tried to set breakpoints and look at the for loop, but I still don’t understand why it happens that the array adds old data to new ones with each iteration
CodePudding user response:
Since you're calling setChart
from viewWillAppear
, you'll be appending to many items in your array (if the view appears/disappears in a single session). You need to clear the variables appropriately, or just overwrite them entirely.
Unrelated, but you can greatly simplify this for loop code:
Start:
func setChart1() {
var entries: [ChartDataEntry] = []
for entry in 0..<(self.cellArr.count) {
if self.cellArr.count > 0 {
let dataEntry = PieChartDataEntry(value: Double(self.cellArr[entry].amount), label: String(self.cellArr[entry].type))
entries.append(dataEntry)
}
}
updateSorting(values: entries)
}
Remove useless if
statement:
func setChart2() {
var entries: [ChartDataEntry] = []
for entry in 0..<(self.cellArr.count) {
let dataEntry = PieChartDataEntry(value: Double(self.cellArr[entry].amount), label: String(self.cellArr[entry].type))
entries.append(dataEntry)
}
updateSorting(values: entries)
}
Replace manually constructed range of indices with a simple Array.indices
:
func setChart3() {
var entries: [ChartDataEntry] = []
for entry in self.cellArr.indices { // "entry" is a total misnomer. It's not an entry, it's an index that can be used to get an entry
let dataEntry = PieChartDataEntry(value: Double(self.cellArr[entry].amount), label: String(self.cellArr[entry].type))
entries.append(dataEntry)
}
updateSorting(values: entries)
}
Realize that you don't even need the indices, you only actually care about the values themselves:
func setChart4() {
var entries: [ChartDataEntry] = []
for entry in self.cellArr {
let dataEntry = PieChartDataEntry(value: Double(entry.amount), label: String(entry.type))
entries.append(dataEntry)
}
updateSorting(values: entries)
}
Inline local variable (its name adds no useful information):
func setChart5() {
var entries: [ChartDataEntry] = []
for entry in self.cellArr {
entries.append(PieChartDataEntry(value: Double(entry.amount), label: String(entry.type)))
}
updateSorting(values: entries)
}
Notice that this is just a map
operation:
func setChart6() {
var entries: [ChartDataEntry] = self.cellArr.map { entry in
PieChartDataEntry(value: Double(entry.amount), label: String(entry.type)))
}
updateSorting(values: entries)
}
entries
can now be immutable, and can use type inference:
func setChart7() {
let entries = self.cellArr.map { PieChartDataEntry(value: Double($0.amount), label: String($0.type))) }
updateSorting(values: entries)
}
CodePudding user response:
I put the array of entries
into a class and cleared it in the setChart7
function
class HomeViewController: UIViewController {
var pieChart = PieChartView()
var entries: [ChartDataEntry] = []
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.setChart()
}
func setChart7() {
entries.removeAll()
let entries = self.cellArr.map { PieChartDataEntry(value: Double($0.amount), label: String($0.type))) }
updateSorting(values: entries)
}
}