web-dev-qa-db-fra.com

Comment ajouter des chaînes sur l'axe X dans les graphiques iOS?

Avec la nouvelle version, j'avais quelques problèmes pour créer des graphiques, le code précédent était le suivant:

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
}

Vous pouvez transmettre les valeurs, par exemple un tableau de mois, en utilisant la ligne:

let chartData = BarChartData(xVals: months, dataSet: chartDataSet)

Après la nouvelle version, le code pour implémenter le même graphique est le suivant:

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
}

J'essayais quelques heures mais je ne pouvais pas trouver un moyen de modifier les valeurs de l'axe X. J'espère que quelqu'un pourra m'aider, merci !!

J'ai trouvé la solution, un autre peut peut-être résoudre ce problème mieux, sans créer une nouvelle classe, et bien c'est ce que j'ai trouvé:

Vous devez d’abord créer une nouvelle classe, qui sera votre classe de formatage et ajouter l’interface IAxisValueFormater, puis vous utiliserez la méthode stringForValue pour personnaliser les nouvelles valeurs, il faut deux paramètres, le premier est la valeur réelle l’index) et second est l’axe où se trouve la valeur.

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)]
  }   
}

Maintenant, dans votre fichier au début de votre fonction setChart (), vous devez créer deux variables, une pour votre classe de formatage et une pour la classe d'axes:

let formato:BarChartFormatter = BarChartFormatter()
let xaxis:XAxis = XAxis()

Ensuite, continuez à la fin de la boucle in et transmettez l'index et l'axe à votre variable de formatage:

formato.stringForValue(Double(i), axis: xaxis)

Après avoir bouclé, ajoutez le format à votre variable d’axe:

xaxis.valueFormatter = formato

La dernière étape consiste à ajouter le nouveau xaxisformatted à barChartView:

barChartView.xAxis.valueFormatter = xaxis.valueFormatter

Et ce sont toutes les autres lignes de la fonction setChart (), gardez-les où elles sont, j'espère que cela pourra vous aider.

Bonjour, récemment, j'ai rencontré le même problème et l'ai résolu de cette façon.

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

    }
}

A la fin, ajoutez simplement l'extension pour le délégué

extension ViewController: IAxisValueFormatter {

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

Découvrez cette solution via ce lien https://medium.com/@skoli/using-realm-and-charts-with-Swift-3-in-ios-10-40c42e3838c0#.minfe6kuk

12
Harshit Goel

Comme beaucoup de gens l'ont dit, vous pouvez créer une classe ou étendre avec le type IAxisValueFormatter, mais vous pouvez facilement utiliser la méthode suivante qui ne prend que 3 lignes:

self.chartView.xAxis.valueFormatter = DefaultAxisValueFormatter(block: {(index, _) in
    return xStrings[Int(index)]
})

voici ma fonction setChart () au cas où certains d'entre vous trouveraient intéressantes certaines de mes personnalisations:

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
}

l'entrée est une structure que j'ai créée:

struct entry {
    var timestamp: Int
    var temperature: Double
}
6
Damien Bannerot

Une méthode plus simple pour implémenter la suggestion ci-dessus si vous sous-classez un graphique consiste à implémenter IAxisValueFormatter protocol dans votre sous-classe elle-même.

class CustomGraphView : LineChartView, ChartViewDelegate, IAxisValueFormatter {}

comme ça...

public func stringForValue(_ value: Double, axis: Charts.AxisBase?) -> String
{
    return "My X Axis Label Str";  // Return you label string, from an array perhaps.
}

Puis dans votre init () 

self.xAxis.valueFormatter = self;
6
RedHotPawn.com

La solution la plus simple:

barChartView.xAxis.valueFormatter = IndexAxisValueFormatter(values: months)
barChartView.xAxis.granularity = 1
0
Zoltan Vinkler