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 ChartViewController
and 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:
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):
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?