Reputation: 1450
I'm using the Charts framework and I'm experiencing some very weird behavior in my line chart.
When I segue to the ChartViewContoller
and the default selection has data, the chart renders normally:
but if I segue to this view controller when the default selection doesn't have any data and then select an item that has data, it looks like this:
1) segue to this:
2) then select an item that has data:
Of course viewDidLoad
is called when I segue to the view controller and as long as the default selection has data when I segue to it, I can select another item that has data or doesn't and the chart will continue to render properly. So the difference appears to be in viewDidLoad
but I've tried everything I can think of but nothing fixes the problem. Here's my viewDidLoad
:
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(hexString: "232B35")
self.title = "1RM"
chartView.delegate = self
chartView.chartDescription?.enabled = false
let leftAxis = chartView.leftAxis
leftAxis.axisMinimum = 190
leftAxis.labelTextColor = NSUIColor.white
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom
xAxis.axisMinimum = 0
xAxis.granularity = 1
xAxis.axisLineWidth = 5
xAxis.valueFormatter = self
xAxis.labelTextColor = NSUIColor.white
chartView.configureDefaults()
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()
chartView.setVisibleXRangeMaximum(7)
chartView.animate(yAxisDuration: 1.0)
}
here's what's happening in fetchData()
:
func fetchData() {
chartView.data = nil
let liftName = UserDefaults.selectedLiftForChart()
let liftEvents = dataManager.fetchLiftsEventsOfTypeByName(liftName)
guard liftEvents.count > 0 else {
chartView.noDataText = "There's no \(liftName) data to display"
shouldHideData = true
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]
let intervalBetweenDates: TimeInterval = 3600 * 24 // 3600 = 1 hour
let startDate = (sortedLiftEvents.first?.date)! - intervalBetweenDates
let lastDate = sortedLiftEvents.last?.date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM d"
let dates:[Date] = intervalDates(from: startDate, to: lastDate!, with: intervalBetweenDates)
days = dates.map {dateFormatter.string(from: $0)}
generateLineData()
}
and finally, this is the generateLineData
method:
func fetchData() {
chartView.data = nil
let liftName = UserDefaults.selectedLiftForChart()
let liftEvents = dataManager.fetchLiftsEventsOfTypeByName(liftName)
guard liftEvents.count > 0 else {
chartView.noDataText = "There's no \(liftName) data to display"
shouldHideData = true
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]
let intervalBetweenDates: TimeInterval = 3600 * 24 // 3600 = 1 hour
let startDate = (sortedLiftEvents.first?.date)! - intervalBetweenDates
let lastDate = sortedLiftEvents.last?.date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM d"
let dates:[Date] = intervalDates(from: startDate, to: lastDate!, with: intervalBetweenDates)
days = dates.map {dateFormatter.string(from: $0)}
generateLineData()
}
I've tried putting chartView.setVisibleXRangeMaximum(7)
in the method that sets the chart data and verified that chartView.visibleXRange
is 7 each time the chart is rendered but it doesn't make a difference. I've also made sure that the max XRange
is being set after the data is set for the chart.
Is there anything else I can try or is this perhaps a bug that hasn't been fixed yet?
Thanks
Upvotes: 0
Views: 573
Reputation: 1450
Well I finally figured it out. I knew from reading the documentation that some properties must be set after the chart data is handed to the chart. It was not entirely clear which properties but through lots of debugging and process of elimination I determined it was the xAxis properties that needed to be reset whenever the data changed.
Now, when the data is changed I call my new function:
func resetxAxis() {
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom
xAxis.axisMinimum = 0
xAxis.granularity = 1
xAxis.axisLineWidth = 5
xAxis.valueFormatter = self
}
This had been in my viewDidLoad
method so I made the above method out of it and can call it any time it's needed.
Upvotes: 1