首页 > 解决方案 > How to reload Linechart Data which is coming from external API in Swift?

问题描述

I am working in an iOS App where I am retrieving data from an API and displaying it in a LineChart. Data is being retrieved as a JSON. I have also shown the tableview where the data is shown correctly. But in case of LineChart, I am facing problems. As data is coming from Alamofire request, which is asynchronous in nature, the chart is being drawn before the data is coming. Can anyone suggest me the best course of action in this regard.

//
//  ICLFundPerformanceChart.swift
//  iVest
//
//  Created by Rashed on 16/9/19.
//  Copyright © 2019 Impress Capital Limited. All rights reserved.
//

import UIKit
import Charts
import Alamofire
import SwiftyJSON

protocol FundPerformanceChartToFundPerformance {
    func backToFundPerformanceFromFundPerformanceChart()
}

class ICLFundPerformanceChart: UIViewController {

    var delegate : FundPerformanceChartToFundPerformance!
    @IBOutlet weak var backImageButton: UIButton!
    @IBOutlet weak var lineChartView: LineChartView!
    
    var navId : Int!
    var url : String!
    var listOfNAV = [BalancedFundNav]()
    
    
    var navChartLevel = [String]()
    var navChartData = [Double]()
    
    override func viewDidLoad() {
        
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        backImageButton.setImage(UIImage(named: "keyboard-left-arrow-button"), for: UIControl.State.normal)
        urlSelector(navTag: navId)
        loadNavData(url: url)
        loadChartData()
        
        // Do any additional setup after loading the view.
        //print(navId)
    }
    
    @IBAction func backButtonPressed(_ sender: Any) {
        delegate?.backToFundPerformanceFromFundPerformanceChart()
        self.dismiss(animated: true, completion: nil)
    }
    
    func urlSelector(navTag : Int){
        let urlGenerator = UrlGenerator()
        url = urlGenerator.generateURL(navId: navTag)
    }
    
    func loadNavData(url : String){
        Alamofire.request(url, method: .post).responseJSON{
            response in
            if response.result.isSuccess{
                
                print("Response Success")
                
                let navDataJSON : JSON = JSON(response.result.value!)
                
                self.updateChartData(json: navDataJSON)
                
            }else{
                
            }
        }
    }
    
    func updateChartData(json : JSON){
        
        print("Updating data")
        guard let dataDict = json.array, !dataDict.isEmpty
            else {
                return
        }
        var navDataJSONArray = [JSON]()
        navDataJSONArray = dataDict
        for nav in navDataJSONArray{
            //print(nav["fund_nav_buy"])
            
            
            let navObject : BalancedFundNav = BalancedFundNav(navAsOnDate: nav["nav_as_on_date"].string!, navAtMarket: nav["fund_nav_market"].double!, navAtSell: nav["fund_nav_sell"].double!, navAtCost: nav["fund_nav_cost"].double!, navValidAt: nav["fund_nav_validity"].string!)
            
            self.listOfNAV.append(navObject)
            
            print(navObject.navAsOnDate!)
            
        }
        //listOfNAV = listOfNAV.reversed()
        print("data updated")
        //lineChartView.reloadInputViews()
        lineChartView.data?.notifyDataChanged()
        lineChartView.notifyDataSetChanged()
        
    }
    
    
    func loadChartData(){
        
        for nav in listOfNAV{
            navChartLevel.append(nav.navAsOnDate)
            navChartData.append(nav.navAtMarket)
        }
        
        setChart(dataPoints: navChartLevel, values: navChartData)
    }
    
    func setChart (dataPoints : [String], values : [Double]){
        
        var dataEntries : [ChartDataEntry] = []
        
        for i in 0..<dataPoints.count {
            
            let dataEntry = ChartDataEntry(x: Double(i), y: values[i])
            dataEntries.append(dataEntry)
        }
        var colors : [UIColor] = []
        for i in 0...dataPoints.count{
            let red = Double(arc4random_uniform(256))
            let green = Double(arc4random_uniform(256))
            let blue = Double(arc4random_uniform(256))
            
            let color = UIColor(red: CGFloat(red/255), green: CGFloat(green/255), blue: CGFloat(blue/255), alpha: 1.0)
            
            colors.append(color)
        }
        
        let lineChartDataSet = LineChartDataSet(entries: dataEntries, label: "NAV")
        lineChartDataSet.colors = colors
        let lineChartData = LineChartData(dataSets: dataPoints as? [IChartDataSet])
        lineChartView.data = lineChartData
    }
    
  

}

Thank you for your kind support in this regard.

Edit:

I have completed the task in different manner. I created a singleton class which would store the value I need and the chart got the data while it was being loaded. But to me it is not the best solution. So waiting for someone's kind reply.

标签: iosswiftalamofireswifty-json

解决方案


在您的 viewDidLoad() 方法中,您调用了 loadChartData()。此方法包含折线图的数据处理,但此时我们没有任何数据。在 loadNavData(url: String) 方法中获取数据后,我们应该调用 loadChartData()。

查看是否加载方法应如下所示

override func viewDidLoad() {

        super.viewDidLoad()
        // Do any additional setup after loading the view.
        backImageButton.setImage(UIImage(named: "keyboard-left-arrow-button"), for: UIControl.State.normal)
        urlSelector(navTag: navId)
        loadNavData(url: url)

        // Do any additional setup after loading the view.
        //print(navId)

loadNavData(url: String) 方法应该看起来像

func loadNavData(url : String){
        Alamofire.request(url, method: .post).responseJSON{
            response in
            if response.result.isSuccess{

                print("Response Success")

                let navDataJSON : JSON = JSON(response.result.value!)
                loadChartData()
                self.updateChartData(json: navDataJSON)


            }else{

            }
        }
    }

推荐阅读