A J
A J

Reputation: 441

How to use date for x-Axis in SwiftChart?

I am trying to draw line chart in my project using SwiftChart pod. I am getting response from API as ["activity_count":0 , "date": "2020-10-31"] but graph works on double values so I don't know How I draw the chart.

import UIKit
import SwiftChart
class AnalyticsViewController: UIViewController {
    @IBOutlet weak var graphContainer: UIView!
    var graphData = [(x:0, y: 0.0)]
    var graphpResponseData = [[String: Any]]()
    override func viewDidLoad() {
        super.viewDidLoad()
    graphpResponseData.append(["activity_count":0 , "date": "2020-10-31"])
    graphpResponseData.append(["activity_count":2 , "date": "2020-10-30"])
    graphpResponseData.append(["activity_count":1 , "date": "2020-10-29"])
    graphpResponseData.append(["activity_count":29 , "date": "2020-10-28"])
    graphpResponseData.append(["activity_count":1 , "date": "2020-10-27"])
    graphpResponseData.append(["activity_count":0 , "date": "2020-10-26"])
    graphpResponseData.append(["activity_count":0 , "date": "2020-10-25"])
    graphpResponseData.append(["activity_count":0 , "date": "2020-10-24"])
    graphpResponseData.append(["activity_count":0 , "date": "2020-10-23"])
    graphpResponseData.append(["activity_count":0 , "date": "2020-10-22"])
    
   ???? unable to proceed
    //let chart = Chart(frame: CGRect(x: 0, y: 0, width: 300, height: 100))
            //let series = ChartSeries(data: graphData)
    //chart.add(series)
    //chart.xLabels = [1, 2, 3, 4]
    //chart.xLabelsFormatter = { String(Int(round($1))) + "Oct" }
    //graphContainer.addSubview(chart)
}


}

desired output enter image description here

Upvotes: 0

Views: 327

Answers (1)

The Swift Coder
The Swift Coder

Reputation: 442

I just had to solve this issue. I was using the day of the month of each date in memory for the x-axis, but it turned out that this would cause the graph to act unexpectedly and show randomly plotted points when the month changed.

I also tried using timestamps for x (of type Double, which would be accepted by the ChartSeries's data initializer, but this failed too.

The solution I found was to use an increment of one for each point on the x-axis, and using an array of [Date] whose indices corresponded with the order of the datapoints in your chart's data property (for the sake of example, call this correspondingDates). Inside of chart.xLabelsFormatter, I'd access this array using correspondingDates[value]. From there, I used two dateFormatter extensions to access the values.

Here's the code:

chart.xLabelsFormatter = { (index,value) in        
 //Format for label
 let date = correspondingDates[Int(value)]
 let dayAbbr = DateFormatter.getDay(date: date)
 let monthAbbr = DateFormatter.getMonth(date: date)
 return monthAbbr + "-" + dayAbbr

Extensions for DateFormatter:

extension DateFormatter{
  
  /// Used specifically to get the Month Abrreviation (ie Feb), but can be used for formatting in other ways.
  /// - Parameter format: Can be 'LLL' for the month abbreviated to 3 letters, or something like 'D/MM/Y'
  /// - Returns: Returns the String version of the date, with precision at any level
  static func getMonth(format:String = "LLL",date: Date = Date())->String{
      let formatter = DateFormatter()
      let today = date // formatter.da(from: Calendar.current.dateComponents([.day], from: Date()))
  
      formatter.dateFormat = format
      let string = formatter.string(from: today)
      return string
  }
  
  
  /// Used specifically to get the Day Abrreviation (ie 05 or 27), but can be used for formatting in other ways.
  /// - Parameters:
  ///   - format: Can be 'LLL' for the month abbreviated to 3 letters, or something like 'D/MM/Y'
  ///   - date: optionally pass in your own date
  /// - Returns:  Returns the String version of the day, with precision at any level
  static func getDay(format:String = "dd",date: Date = Date())->String{
      let formatter = DateFormatter()
      let today = date // formatter.da(from: Calendar.current.dateComponents([.day], from: Date()))
  
      formatter.dateFormat = format
      let string = formatter.string(from: today)
      return string
  }
  
}

Upvotes: 1

Related Questions