How to add Strings on X Axis in iOS-charts?
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;
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
}
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.
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