27

I've recently started using the ios charts library and am having trouble finding information on how to manipulate the x-axis with the swift3 update.

What I want to do is label the x-axis with time values, e.g. 2:03:00, 2:03:01, 2:03:02, etc. In the tutorials I find online, this seems to be very easy; many of them use months of the year as the x-axis label.

However, in the swift3 update, charts now initializes values with x and y values, and I am not sure how to use labels in this version of the library. Does anyone know how to create labels in charts with swift3?

Léo Natan
  • 56,823
  • 9
  • 150
  • 195
matt
  • 291
  • 1
  • 3
  • 5
  • Would this question/answer help? : [link](http://stackoverflow.com/questions/39960302/how-to-add-labels-for-xaxis-for-barchartview-in-ios-charts) – Lyra Nov 01 '16 at 13:19
  • Please consider to comment about why you are votting down this question – pylover Jan 03 '17 at 09:46

6 Answers6

69

Proper Solution for X-Axis String labels in Swift 3+

let months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
    barChartView.xAxis.valueFormatter = IndexAxisValueFormatter(values:months)
    barChartView.xAxis.granularity = 1
Shrestha Ashesh
  • 1,769
  • 2
  • 13
  • 12
  • granularity will set the proper position for xValues under the bar lines. – Maryam Fekri Apr 15 '17 at 07:19
  • 1
    I use your code to show the xValues but It shows month by alternate basis – Raj Aggrawal Jun 02 '17 at 11:55
  • 1
    Doesn't this rely on the assumption that you have data for each month? If you don't have data for, say, April, wouldn't the value formatter never pass the index in that corresponds to April / wouldn't the April label never be generated? – Brian Sachetta Jul 13 '18 at 20:58
  • Thanks man you literally saved me. I spent 2 hrs banging my head. – Aisha Jun 12 '20 at 20:19
16

Create a class like this:

    import Foundation
    import Charts

    @objc(BarChartFormatter)
    class ChartFormatter: NSObject, IAxisValueFormatter{

    let months: [String] = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

    func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        return months[Int(value)]
    }

}

Set the x-Axis like this:

    let xAxis = XAxis()
    let chartFormmater = ChartFormatter()
    
    for i in index{
        chartFormmater.stringForValue(Double(i), axis: xAxis)
    }
    
    xAxis.valueFormatter = chartFormmater
    chartView.xAxis.valueFormatter = xAxis.valueFormatter
Borzh
  • 5,069
  • 2
  • 48
  • 64
Hamed
  • 1,678
  • 18
  • 30
  • Do you know how to do this with Pie Charts? since xAxis is not a thing in pie charts and the labels initializer was also removed – Jesus Rodriguez Apr 04 '17 at 11:45
  • Excuse me, I don't now :( – Hamed Apr 04 '17 at 14:02
  • 1
    it took me a while, but in the newest Charts library version, the Pie Chart has a new entry initializer named pieChartDataEntry which takes a label as an argument ` let entry = PieChartDataEntry(value: Double(entryValue), label: label)` – Jesus Rodriguez Apr 04 '17 at 14:05
  • 1
    I've used this solution but it didn't help me. Could you please see my [question](https://stackoverflow.com/questions/46618636/how-to-add-string-labels-xaxis-labels-to-horizontal-bar-in-charts-framework)? – Amir Shabani Oct 08 '17 at 10:29
  • Amir, I'll see my project, I forgot it. @AmirShabani – Hamed Oct 09 '17 at 13:52
  • @HamedAkhlaghi I found the answer, Thanks a lot :) – Amir Shabani Oct 09 '17 at 14:03
  • was my answer helpful? @AmirShabani – Hamed Oct 09 '17 at 14:18
  • I had a mistake on my code, by the way, I used something like your codes – Amir Shabani Oct 09 '17 at 14:57
  • I could be wrong but I don't think this solution actually works. Does anyone know why stringForValue is called in a for loop without doing anything else? That method seems to just return a string and doesn't explicitly set the labels. – Brian Sachetta Jul 13 '18 at 20:07
10

Swift 5.5

I'm having pretty good results using standard DateFormatter() I'm converting UNIX timestamp to format day.month

final class XAxisNameFormatter: NSObject, AxisValueFormatter {
    
    func stringForValue( _ value: Double, axis _: AxisBase?) -> String {
        
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "dd.MM"
        
        return formatter.string(from: Date(timeIntervalSince1970: value))
    }
    
}

Usage:

self.lineChartView.xAxis.valueFormatter = XAxisNameFormater()
self.lineChartView.xAxis.granularity = 1.0
Dick Thunder
  • 378
  • 3
  • 17
6

I propose to use more flexible and pretty solution. You should have a formatter class like this:

final class MonthNameFormater: NSObject, IAxisValueFormatter {
    func stringForValue( _ value: Double, axis _: AxisBase?) -> String {
        return Calendar.current.shortMonthSymbols[Int(value)]
    }
}

Set up this type to your barChartView:

barChartView.xAxis.valueFormatter = MonthNameFormater()
barChartView.xAxis.granularity = 1.0

As a result you will have: Jan, Feb, ..., Dec In addition if you want to change presentation kind you should change shortMonthSymbols with some other: monthSymbols, veryShortMonthSymbols, standaloneMonthSymbols

biloshkurskyi.ss
  • 1,358
  • 3
  • 15
  • 34
  • One thing I don't quite understand about the latest version of the library is: what if we want to have labels for months for which no data is entered? Say there is no data for March but we still want to show "Mar" in the chart. Wouldn't the "value" in stringForValue never equal 2 (March)? – Brian Sachetta Jul 13 '18 at 20:24
  • I was way over thinking this problem. This solution is so simple! Thank you for this!! – Jordan Oct 04 '18 at 18:02
2

You can do this by creating your own formatter for the time. Below I mention sample code for that for your reference.

    public class DateValueFormatter: NSObject, AxisValueFormatter {
    private let dateFormatter = DateFormatter()

    override init() {
        super.init()
        dateFormatter.dateFormat = "HH:mm:ss"
    }

    public func stringForValue(_ value: Double, axis: AxisBase?) -> String {
        return dateFormatter.string(from: Date(timeIntervalSince1970: value))
    }
}

To set your value just use below code.

self.yourChart.xAxis.valueFormatter = DateValueFormatter()
self.yourChart.xAxis.granularity = 1.0
Bhavesh Patel
  • 596
  • 4
  • 17
0

I had problems creating the class as the previous answers

'No type or protocol named 'IChartAxisValueFormatter'

I removed the NSObject inheritance and left only IAxisValueFormatter like here:

final class XAxisNameFormater: IAxisValueFormatter {.....
Ronaldo Albertini
  • 1,329
  • 20
  • 24