可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
With the new release i had some troubles to create some graphs the previous code was:
func setChart(dataPoints: [String], values: [Double]) {
var dataEntries: [BarChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = BarChartDataEntry(value: values[i], xIndex: i)
dataEntries.append(dataEntry)
}
let chartDataSet = BarChartDataSet(yVals: dataEntries, label: "Units Sold")
let chartData = BarChartData(xVals: months, dataSet: chartDataSet)
barChartView.data = chartData
}
You can pass the values for example an array of months using the line:
let chartData = BarChartData(xVals: months, dataSet: chartDataSet)
After the new release the code to implement the same graph is:
func setChart(dataPoints: [String], values: [Double]) {
var dataEntries: [BarChartDataEntry] = []
for i in 0..<dataPoints.count {
let dataEntry = BarChartDataEntry(x: Double(i+2), y:values[i], data: months )
dataEntries.append(dataEntry)
}
let chartDataSet = BarChartDataSet(values: dataEntries, label: "Units Sold")
let chartData = BarChartData()
chartData.addDataSet(chartDataSet)
barChartView.data = chartData
}
I was trying a few hours but i couldn't find a way to modify the X axis values, i hope someone can help me, thanks!!
回答1:
I found the solution, maybe another one can solve this problem in a better way, without create a new class, well this is what I found:
First you nedd to create a new class, which will be your formatter class and add the IAxisValueFormater interface, then you use the method stringForValue to customize the new values, it takes two parameters, the first is the actual value (you can see it like the index) and second is the axis where the value is.
import UIKit
import Foundation
import Charts
@objc(BarChartFormatter)
public class BarChartFormatter: NSObject, IAxisValueFormatter
{
var months: [String]! = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
public func stringForValue(value: Double, axis: AxisBase?) -> String
{
return months[Int(value)]
}
}
Now in your file at the begining of your setChart() function you have to create two variables one for your formatter class and one for the axis class:
let formato:BarChartFormatter = BarChartFormatter()
let xaxis:XAxis = XAxis()
Next, go ahead at the end of the for in loop and pass the index and axis to your formatter variable:
formato.stringForValue(Double(i), axis: xaxis)
After looping add the format to your axis variable:
xaxis.valueFormatter = formato
The final step is to add the new xaxisformatted to the barChartView:
barChartView.xAxis.valueFormatter = xaxis.valueFormatter
And that's all the other lines in the setChart() function just keep it where they are, I hope it can help you.
回答2:
Hello recently I encountered the same problem and solved it this way-
class ViewController: UIViewController {
var months: [String]!
var unitsSold = [Double]()
weak var axisFormatDelegate: IAxisValueFormatter?
@IBOutlet var viewForChart: BarChartView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
axisFormatDelegate = self
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
unitsSold = [20.0, 4.0, 6.0, 3.0, 12.0, 16.0, 4.0, 18.0, 2.0, 4.0, 5.0, 4.0]
// setChart(_ dataPoints:months,_ forY: unitsSold)
setChart(dataEntryX: months, dataEntryY: unitsSold)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setChart(dataEntryX forX:[String],dataEntryY forY: [Double]) {
viewForChart.noDataText = "You need to provide data for the chart."
var dataEntries:[BarChartDataEntry] = []
for i in 0..<forX.count{
// print(forX[i])
// let dataEntry = BarChartDataEntry(x: (forX[i] as NSString).doubleValue, y: Double(unitsSold[i]))
let dataEntry = BarChartDataEntry(x: Double(i), y: Double(forY[i]) , data: months as AnyObject?)
print(dataEntry)
dataEntries.append(dataEntry)
}
let chartDataSet = BarChartDataSet(values: dataEntries, label: "Units Sold")
let chartData = BarChartData(dataSet: chartDataSet)
viewForChart.data = chartData
let xAxisValue = viewForChart.xAxis
xAxisValue.valueFormatter = axisFormatDelegate
}
}
At the end simply add the extension for the delegate
extension ViewController: IAxisValueFormatter {
func stringForValue(_ value: Double, axis: AxisBase?) -> String {
return months[Int(value)]
}
}
Figured this solution out through this link
https://medium.com/@skoli/using-realm-and-charts-with-swift-3-in-ios-10-40c42e3838c0#.minfe6kuk
回答3:
A cleaner way to implement the suggestion above if you are subclassing a graph is to implement IAxisValueFormatter protocol in your subclass itself
class CustomGraphView : LineChartView, ChartViewDelegate, IAxisValueFormatter {}
like this...
public func stringForValue(_ value: Double, axis: Charts.AxisBase?) -> String
{
return "My X Axis Label Str"; // Return you label string, from an array perhaps.
}
Then in your init()
self.xAxis.valueFormatter = self;
回答4:
As many people said you can create a class or extend with the type IAxisValueFormatter, but you can easily use the following method which only take 3 lines :
self.chartView.xAxis.valueFormatter = DefaultAxisValueFormatter(block: {(index, _) in
return xStrings[Int(index)]
})
here's my setChart() function in case some of you find some of my customization interesting :
func setChartView(entriesData: [entry]) {
var chartEntries: [ChartDataEntry] = []
var xStrings: [String] = []
let sortedentriesData = entriesData.sorted { (s1: entry, s2: entry) -> Bool in
return s1.timestamp < s2.timestamp
}
for (i, entry) in sortedentriesData.enumerated() {
let newEntry = ChartDataEntry(x: Double(i), y: entry.temperature)
chartEntries.append(newEntry)
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .medium
dateFormatter.dateStyle = .none
xStrings.append("\(dateFormatter.string(from: Date.init(timeIntervalSince1970: TimeInterval(entry.timestamp))))")
}
let set: LineChartDataSet = LineChartDataSet(values: chartEntries, label: "°C")
set.setColor(NSUIColor.blue, alpha: CGFloat(1))
set.circleColors = [NSUIColor.blue]
set.circleRadius = 3
set.mode = LineChartDataSet.Mode.cubicBezier
let data: LineChartData = LineChartData(dataSet: set)
self.chartView.xAxis.labelRotationAngle = -90
self.chartView.xAxis.valueFormatter = DefaultAxisValueFormatter(block: {(index, _) in
return xStrings[Int(index)]
})
self.chartView.xAxis.setLabelCount(xStrings.count, force: true)
self.chartView.data = data
}
entry is a struct I created :
struct entry {
var timestamp: Int
var temperature: Double
}