I'm trying out @danielgindi's Charts framework to create a Line Chart but my data won't display on the chart:
I started with the CombinedChartViewController demo because I wanted some of the features that it has. My plan was to remove the chart data types I didn't need and leave the LineChartData.
Before making a final change, the data displayed properly:
Then, I changed the type of data from CombinedChartData to LineChartData and assign the LineChartData to chartView.data instead of data.lineData. As soon as I did this, the data stopped displaying.
I've compared by code to the LineChart1ViewController code and don't see any material difference that could cause this. I've poured through the documentation and the issues on Github and looked through all of the related questions I could find on SO. I've confirmed that my data is ordered properly (as suggested) but it made no difference. And as I mentioned, that same data renders properly when using CombinedChartData.
I've struggled with this for a couple of days and I'm out of ideas to try. Can anybody offer any ideas I haven't yet tried?
import UIKit
import Charts
var shouldHideData: Bool = false
class ChartViewController: UIViewController, ChartViewDelegate {
@IBOutlet var chartView: LineChartView!
fileprivate let dataManager = CoreDataHelper()
fileprivate var sortedLiftEvents: [LiftEvent] = []
var days: [String]? = []
override func viewDidLoad() {
super.viewDidLoad()
self.title = "1RM"
chartView.delegate = self
chartView.chartDescription?.enabled = false
let leftAxis = chartView.leftAxis
leftAxis.axisMinimum = 0
leftAxis.labelTextColor = NSUIColor.white
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom
xAxis.axisMinimum = 0
xAxis.granularity = 1
xAxis.valueFormatter = self
xAxis.labelTextColor = NSUIColor.white
chartView.rightAxis.enabled = false // this fixed the extra xAxis grid lines
chartView.backgroundColor = NSUIColor(red: 35/255.0, green: 43/255.0, blue: 53/255.0, alpha: 1.0)
fetchData()
self.updateChartData()
chartView.configureDefaults()
chartView.setVisibleXRangeMaximum(5)
view.backgroundColor = UIColor(hexString: "232B35")
}
private func fetchData() {
let liftEventTypeUuid = "98608870-E3CE-476A-B1E4-018D2AE4BDBF"
// get all Bench Press events
let liftEvents = dataManager.fetchLiftsEventsOfType(liftEventTypeUuid)
// put them into a Dictionary grouped by each unique day
let groupedEvents = Dictionary(grouping: liftEvents, by: { floor($0.date.timeIntervalSince1970 / 86400) })
let maxEventsPerDay = groupedEvents.map { $1.max(by: { $0.oneRepMax < $1.oneRepMax }) }
// MARK: - Fix the silly unwrapping
sortedLiftEvents = maxEventsPerDay.sorted(by: { $0?.date.compare(($1?.date)!) == .orderedAscending }) as! [LiftEvent]
/// 3600 = 1 hour
/// 1 day
let startingDate = sortedLiftEvents.first?.date
let endDate = sortedLiftEvents.last?.date
let intervalBetweenDates:TimeInterval = 3600 * 24
let dates:[Date] = intervalDates(from: startingDate!, to: endDate!, with: intervalBetweenDates)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM d"
days = dates.map{dateFormatter.string(from: $0)}
}
func updateChartData() {
if shouldHideData {
chartView.data = nil
return
}
self.setChartData()
}
func setChartData() {
generateLineData()
}
func generateLineData() {
let entries = sortedLiftEvents.enumerated().map { (arg) -> ChartDataEntry in
let (index, liftEvent) = arg
return ChartDataEntry(x: Double(index), y: liftEvent.oneRepMax.value)
}
// style the line to be drawn
let set = LineChartDataSet(values: entries, label: "Line DataSet")
set.setColor(UIColor(hexString: "768DAA"))
set.lineWidth = 1.5
set.setCircleColor((UIColor(hexString: "768DAA")))
set.circleHoleColor = UIColor(red: 35/255, green: 43/255, blue: 53/255, alpha: 1)
set.circleRadius = 4
set.circleHoleRadius = 2
// set.fillColor = (UIColor(hexString: "F20B27"))
set.mode = .linear
set.drawValuesEnabled = true
set.valueFont = .systemFont(ofSize: 10)
set.valueTextColor = UIColor(red: 240/255, green: 238/255, blue: 70/255, alpha: 1)
set.axisDependency = .left
let data = LineChartData(dataSet: set)
chartView.data = data
}
func intervalDates(from startingDate:Date, to endDate:Date, with interval:TimeInterval) -> [Date] {
guard interval > 0 else { return [] }
var dates:[Date] = []
var currentDate = startingDate
while currentDate <= endDate {
currentDate = currentDate.addingTimeInterval(interval)
dates.append(currentDate)
}
return dates
}
}
extension ChartViewController: IAxisValueFormatter {
func stringForValue(_ value: Double, axis: AxisBase?) -> String {
guard let days = days else { return "" }
return days[Int(value) % days.count]
}
}
}
}
The ChartDataEntry's in entries look like this:
▿ 0 : ChartDataEntry, x: 0.0, y 209.0
▿ 1 : ChartDataEntry, x: 1.0, y 209.0
▿ 2 : ChartDataEntry, x: 2.0, y 246.0
▿ 3 : ChartDataEntry, x: 3.0, y 233.333333333333
▿ 4 : ChartDataEntry, x: 4.0, y 220.0
▿ 5 : ChartDataEntry, x: 5.0, y 234.0
▿ 6 : ChartDataEntry, x: 6.0, y 220.0
▿ 7 : ChartDataEntry, x: 7.0, y 240.0
▿ 8 : ChartDataEntry, x: 8.0, y 227.5
▿ 9 : ChartDataEntry, x: 9.0, y 239.166666666667
▿ 10 : ChartDataEntry, x: 10.0, y 234.666666666667
...
▿ 90 : ChartDataEntry, x: 90.0, y 220.0
▿ 91 : ChartDataEntry, x: 91.0, y 238.0
▿ 92 : ChartDataEntry, x: 92.0, y 234.0
▿ 93 : ChartDataEntry, x: 93.0, y 220.0
▿ 94 : ChartDataEntry, x: 94.0, y 240.0
▿ 95 : ChartDataEntry, x: 95.0, y 226.666666666667
▿ 96 : ChartDataEntry, x: 96.0, y 227.5
▿ 97 : ChartDataEntry, x: 97.0, y 239.166666666667
▿ 98 : ChartDataEntry, x: 98.0, y 234.666666666667
▿ 99 : ChartDataEntry, x: 99.0, y 240.0
▿ 100 : ChartDataEntry, x: 100.0, y 222.0


entries. Thanks for looking at this. It's driving me nuts.