Search code examples
iosarraysswiftchartsios-charts

How to iterate through Swift array and use data in iOS Chart?


I have a bar chart, which I am trying to populate through data pulled in from an array.

I am trying to iterate through this array in order to populate my chart.

Please note: in this example below there are 3 winningStreakDM variables hardcoded for testing purposes, but in 'real life' the number could be different each API call as it depends on how many 'users' are in that league.

This is why I need to iterate through the array and structure the data to suit.

    let winningStreakDM1 : [String : Any] = [
        "id" : 2,
        "user_name" : "Dicky",
        "winning_streak" : 5
    ]

    let winningStreakDM2 : [String : Any] = [
        "id" : 6,
        "user_name" : "G",
        "winning_streak" : 2
    ]

    let winningStreakDM3 : [String : Any] = [
        "id" : 5,
        "user_name" : "Sultan",
        "winning_streak" : 0
    ]

My issue is that I don't know how to iterate through the initial array to structure my data for it to work with the above code.

This is my full script:

import UIKit
import Charts

class CommunityLeagueStatsVC: UIViewController {


// GRAPHS *********

@IBOutlet weak var chartView: BarChartView!
var values = [BarChartDataEntry]()

// ****************
//********CHART VARIABLES**************//

//WINS LOSSES DRAWS
var winStreak: Double = 0.0

@IBOutlet weak var leagueStatsScrollView: UIScrollView!

var noDefeats: Bool?
var noWins: Bool?
var biggestWin: String?
var biggestWinTeams: String?

var passedCommunityName: String?
@IBOutlet weak var communityName: UILabel!

var playerId2: String?
var communityId2: String?
var eMail2: String?

override func viewDidLoad() {
    super.viewDidLoad()


    let winningStreak =  ["Wins"]
    let gamesWon = [winStreak]
    setWinStreakChart(dataPoints: winningStreak, values: gamesWon)

    let defaults = UserDefaults.standard
    let Email = defaults.string(forKey: "userEmail")
    let playerId = defaults.string(forKey: "playerId")
    let commsId = defaults.string(forKey: "communityId")

    self.playerId2 = playerId
    self.communityId2 = commsId
    self.eMail2 = Email


}

 func setWinStreakChart(dataPoints: [String], values: [BarChartDataEntry]){

    xAxis.valueFormatter = WinningStreakFormatter(chartView: self.chartView)
    let barChartDataSet = BarChartDataSet(values: values, label: "Winning Streak")
    barChartDataSet.colors = ChartColorTemplates.material()

    let barChartData = BarChartData(dataSet: barChartDataSet)
    barChartData.setValueFont(UIFont.systemFont(ofSize: 12.0))
    self.chartView.data = barChartData
}


override func viewDidAppear(_ animated: Bool) {

    let myUrl = URL(string: "http://www.xxx.uk/xxx/getLeagueStats.php")
    var request = URLRequest(url:myUrl!)
    request.httpMethod = "POST"

    let postString = "player_id=\(self.playerId2!)&community_id=\(communityId2!)";

    request.httpBody = postString.data(using: String.Encoding.utf8);
    let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
        DispatchQueue.main.async
            {
                do{

                    let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
                    print (json!)

                       if let dict = json?["leagueStats"] as? [String:AnyObject] {

                          //WINNING STREAK

                        var values = [BarChartDataEntry]()

                        if let dataWinStreak = dict["winningStreak"] as? [[String : Any]] {
                            print ("test one")
                            for (index,item) in dataWinStreak.enumerated() {
                                if let yValue = item["winning_streak"] as? Int, let userName = item["user_name"] as? String {
                                    print ("test two")
                                    let barChartDataEntry = BarChartDataEntry(x: Double(index), y: Double(yValue), data: userName as AnyObject?)
                                    values.append(barChartDataEntry)

                                }
                            }

                            self.setWinStreakChart(dataPoints: ["wins"], values: values)
                        }
        catch{
            print(error)
                }
        }
        }
    task.resume()

}
}

UPDATE:

These are the errors that I am currently receiving:

enter image description here

enter image description here enter image description here

With a bit of playing around and commenting out the line containing the first error I have got to this stage which correctly shows a graph with values, but no xAxis containing the userNames of each player.


Solution

  • You can create array of BarChartDataEntry this way.

    var values = [BarChartDataEntry]()
    
    if let dataWinStreak = dict["winningStreak"] as? [[String : Any]] {
        for (index,item) in dataWinStreak.enumerated() {
            if let yValue = item["winning_streak"] as? Int, let userName = item["user_name"] as? String {
                let barChartDataEntry = BarChartDataEntry(x: index, y: yValue, data: userName)
                values.append(barChartDataEntry)
            }
        }
    }
    //Now use values array
    

    Edit: You just need to change setWinStreakChart function because now you are working with dynamic data not static one.

    func setWinStreakChart(dataPoints: [String], values: [BarChartDataEntry]){
    
        let  xAxis : XAxis = self.chartView.xAxis;
        xAxis.labelFont = UIFont(name: "HelveticaNeue-Light", size: 10.0)!
        xAxis.labelTextColor = UIColor.black
        xAxis.drawAxisLineEnabled = false
        xAxis.drawGridLinesEnabled = true
        xAxis.granularity = 1;
        xAxis.labelPosition = .bottom
    
        xAxis.valueFormatter = WinningStreakFormatter(chartView: self.chartView)
        let barChartDataSet = BarChartDataSet(values: values, label: "Winning Streak")
        barChartDataSet.colors = ChartColorTemplates.material()
    
        let barChartData = BarChartData(dataSet: barChartDataSet)
        barChartData.setValueFont(UIFont.systemFont(ofSize: 12.0))
        self.chartView.data = barChartData
    }
    

    And now call this function after the for loop where we are creating array of BarChartDataEntry.

    self.setWinStreakChart(dataPoints: ["wins"], values: values)