0

I'm using version 3.1.1. of the Charts framework and I'm having trouble getting the viewport to move far enough to the right to show the last value. If I segue to my ChartViewControllerand the current selection has data to display, it moves to a point in the chart that leaves 7 datapoints out of view to the right. However, if I then select another item that doesn't have any data and then select the previous item that has data, it correctly moves the chart so the last datapoint is visible:

enter image description here

When a selection is made, I fetch the appropriate data:

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    let selectedLift = lifts[row]

    UserDefaults.setSelectedLiftForChart(selectedLift)
    delegate.fetchLiftEvents()

}

In fetchLiftEvents() I set the chartView.data to nil if there's no data and this appears to be the only difference between what happens when I first segue to the ChartViewController and when select an item with no data and reselect the previous item:

func fetchLiftEvents() {

    let liftName = UserDefaults.selectedLiftForChart()
    let liftEvents = dataManager.fetchLiftsEventsOfTypeByName(liftName)

    guard liftEvents.count > 0 else {
        chartView.noDataText = "There's no \(liftName) data to display"
        chartView.data = nil

        return }

    // put them into a Dictionary grouped by each unique day
    let groupedEvents = Dictionary(grouping: liftEvents, by: { floor($0.date.timeIntervalSince1970 / 86400) })

    // grab the maximum 1RM from each day
    let dailyMaximums = groupedEvents.map { $1.max(by: { $0.oneRepMax < $1.oneRepMax }) }

    // MARK: - TODO: Fix the silly unwrapping
    sortedLiftEvents = dailyMaximums.sorted(by: { $0?.date.compare(($1?.date)!) == .orderedAscending }) as! [LiftEvent]

    generatexAxisDates(liftEvents: sortedLiftEvents)

    generateLineData(liftEvents: sortedLiftEvents)

}

Both generatexAxisDates(liftEvents: sortedLiftEvents) and generateLineData(liftEvents: sortedLiftEvents) are called in viewDidLoad(), my point being that they're called when the view loads and when a new selection with data is chosen. I'm calling setVisibleXRange(minXRange:maxXRange:) in generateLineData(liftEvents:) so it's always getting called as well:

func generateLineData(liftEvents: [LiftEvent]) {

    // generate the array of ChartDataEntry()...

    // generate set = LineChartDataSet(values: values, label: "Line DataSet")

    let data = LineChartData(dataSet: set)

    chartView.data = data

    chartView.setVisibleXRange(minXRange: 7.0, maxXRange: 7.0)
    chartView.moveViewToX(chartView.chartXMax)

    resetxAxis()

    chartView.configureDefaults()

    chartView.animate(yAxisDuration: 0.8)

}

and resetxAxis() is only doing this:

func resetxAxis() {
    let xAxis = chartView.xAxis
    xAxis.labelPosition = .bottom
    xAxis.axisMinimum = 0
    xAxis.granularity = 1
    xAxis.axisLineWidth = 5
    xAxis.valueFormatter = self
}

I've searched through the documentation and Issues on Github and looked at many related questions on SO, but I'm not able to get this to work. This question seems to be addressing the very same problem I'm having but after trying to apply the solution to my problem, it still persists.

Is there anything else someone can suggest trying?

Update

I found a possible clue to the problem. When I first segue to the chart view (screenshot 1), the bounds of chartView are different after I select an item with no data and then reselect Deadlift (screenshots 2 & 3):

enter image description here

It's the very same data set in each case but initially the height is 389 but then changes to 433. I'm guessing this must affect the scaling but I haven't been able to find where or how the bounds of chartView are set.

Any ideas why this is happening?

Jim
  • 1,260
  • 15
  • 37

1 Answers1

0

I finally figured it out. I was fetching the data that would be displayed on the charts before setting some of the chart properties that should be set prior to setting chartView.data = data. I now set these default properties before fetching and setting the data and it works:

extension BarLineChartViewBase {
    func configureDefaults() {
    backgroundColor = NSUIColor(red: 35/255.0, green: 43/255.0, blue: 53/255.0, alpha: 1.0)

    chartDescription?.enabled = false

    legend.enabled = false

    xAxis.labelPosition = .bottom
    xAxis.avoidFirstLastClippingEnabled = false
    xAxis.gridColor.withAlphaComponent(0.9)

    rightAxis.enabled = false // this fixed the extra xAxis grid lines
    rightAxis.drawLabelsEnabled = false

    for axis in [xAxis, leftAxis] as [AxisBase] {
        axis.drawAxisLineEnabled = true
        axis.labelTextColor = .white
    }

    noDataTextColor = .white
    noDataFont = NSUIFont(name: "HelveticaNeue", size: 16.0)

} 
Jim
  • 1,260
  • 15
  • 37