0

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.

1 Answer 1

1
+50

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)
Sign up to request clarification or add additional context in comments.

10 Comments

I have an error in that I have added this line ` self.setWinStreakChart(dataPoints: ["wins"], values: values)` to the bottom of your code to then call the function but it says ' Cannot convert value of type '[BarChartDataEntry]' to expected argument type '[Double]'. I have updated the question to show the full function and what it is expecting. Thank you!
@RDowns Why are you calling that function your array of BarChartDataEntry is created so don't you need to call now: let barChartDataSet = BarChartDataSet(values: values, label: "Winning Streak")
The api call happens outside of the function to create the chart- so don't I need to call the function to populate it with the data retrieved? I should probably show you the full script- I am out at the moment but will update the question with the full script when I return. Thanks
I have added my full script to the question so you can see what I mean - and hopefully where I am going wrong!
@RDowns I'm currently out from Mac will help you tomorrow.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.