Jim
Jim

Reputation: 1450

Why doesn't my line chart display its data?

I'm trying out @danielgindi's Charts framework to create a Line Chart but my data won't display on the chart:

enter image description here

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:

enter image description here

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

Upvotes: 1

Views: 1590

Answers (1)

Razib Mollick
Razib Mollick

Reputation: 5032

Your view controller code is perfectly okay with my code. Probably you have a class reference problem:

Go to storyboard and change the chart view class from "CombinedChartView" to "LineChartView".

Upvotes: 3

Related Questions