图表的折线图无法正确呈现折线图
Charts' line chart doesn't render line chart properly
我正在使用图表框架,但在我的折线图中遇到了一些非常奇怪的行为。
当我转到 ChartViewContoller
并且默认 selection 有数据时,图表正常呈现:
但是如果我在默认 selection 没有任何数据并且 then select 有数据的项目时转到这个视图控制器,看起来像这样:
1) 转至此:
2) 然后 select 一个包含数据的项目:
当然 viewDidLoad
在我转到视图控制器时会被调用,只要默认的 selection 在我转到它时有数据,我就可以 select 另一个项目有数据或没有数据,图表将继续正确呈现。所以差异似乎在 viewDidLoad
中,但我已经尝试了我能想到的一切,但没有解决问题。这是我的 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)
}
这是 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([=11=].date.timeIntervalSince1970 / 86400) })
// grab the maximum 1RM from each day
let dailyMaximums = groupedEvents.map { .max(by: { [=11=].oneRepMax < .oneRepMax }) }
// MARK: - TODO: Fix the silly unwrapping
sortedLiftEvents = dailyMaximums.sorted(by: { [=11=]?.date.compare((?.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: [=11=])}
generateLineData()
}
最后,这是 generateLineData
方法:
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([=11=].date.timeIntervalSince1970 / 86400) })
// grab the maximum 1RM from each day
let dailyMaximums = groupedEvents.map { .max(by: { [=11=].oneRepMax < .oneRepMax }) }
// MARK: - TODO: Fix the silly unwrapping
sortedLiftEvents = dailyMaximums.sorted(by: { [=11=]?.date.compare((?.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: [=11=])}
generateLineData()
}
我试过将 chartView.setVisibleXRangeMaximum(7)
放在设置图表数据的方法中,并验证每次呈现图表时 chartView.visibleXRange
都是 7,但这没有什么不同。我还确保在为图表设置数据后设置最大值 XRange
。
还有什么我可以尝试的吗?或者这可能是一个尚未修复的错误?
谢谢
嗯,我终于明白了。我通过阅读文档知道,在将图表数据传递给图表后,必须设置一些属性。尚不完全清楚哪些属性,但通过大量调试和消除过程,我确定是 xAxis 属性需要在数据更改时重置。
现在,当数据改变时,我调用我的新函数:
func resetxAxis() {
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom
xAxis.axisMinimum = 0
xAxis.granularity = 1
xAxis.axisLineWidth = 5
xAxis.valueFormatter = self
}
这已经在我的 viewDidLoad
方法中,所以我用它制作了上面的方法,并且可以在需要时随时调用它。
我正在使用图表框架,但在我的折线图中遇到了一些非常奇怪的行为。
当我转到 ChartViewContoller
并且默认 selection 有数据时,图表正常呈现:
但是如果我在默认 selection 没有任何数据并且 then select 有数据的项目时转到这个视图控制器,看起来像这样:
1) 转至此:
2) 然后 select 一个包含数据的项目:
当然 viewDidLoad
在我转到视图控制器时会被调用,只要默认的 selection 在我转到它时有数据,我就可以 select 另一个项目有数据或没有数据,图表将继续正确呈现。所以差异似乎在 viewDidLoad
中,但我已经尝试了我能想到的一切,但没有解决问题。这是我的 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)
}
这是 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([=11=].date.timeIntervalSince1970 / 86400) })
// grab the maximum 1RM from each day
let dailyMaximums = groupedEvents.map { .max(by: { [=11=].oneRepMax < .oneRepMax }) }
// MARK: - TODO: Fix the silly unwrapping
sortedLiftEvents = dailyMaximums.sorted(by: { [=11=]?.date.compare((?.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: [=11=])}
generateLineData()
}
最后,这是 generateLineData
方法:
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([=11=].date.timeIntervalSince1970 / 86400) })
// grab the maximum 1RM from each day
let dailyMaximums = groupedEvents.map { .max(by: { [=11=].oneRepMax < .oneRepMax }) }
// MARK: - TODO: Fix the silly unwrapping
sortedLiftEvents = dailyMaximums.sorted(by: { [=11=]?.date.compare((?.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: [=11=])}
generateLineData()
}
我试过将 chartView.setVisibleXRangeMaximum(7)
放在设置图表数据的方法中,并验证每次呈现图表时 chartView.visibleXRange
都是 7,但这没有什么不同。我还确保在为图表设置数据后设置最大值 XRange
。
还有什么我可以尝试的吗?或者这可能是一个尚未修复的错误?
谢谢
嗯,我终于明白了。我通过阅读文档知道,在将图表数据传递给图表后,必须设置一些属性。尚不完全清楚哪些属性,但通过大量调试和消除过程,我确定是 xAxis 属性需要在数据更改时重置。
现在,当数据改变时,我调用我的新函数:
func resetxAxis() {
let xAxis = chartView.xAxis
xAxis.labelPosition = .bottom
xAxis.axisMinimum = 0
xAxis.granularity = 1
xAxis.axisLineWidth = 5
xAxis.valueFormatter = self
}
这已经在我的 viewDidLoad
方法中,所以我用它制作了上面的方法,并且可以在需要时随时调用它。