ios - 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.
解决方案
在您的 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{
}
}
}
推荐阅读
- css - 子菜单似乎向右移动
- python - 使用python计算日志文件中的时间
- c# - 为什么我首先确保 Azure blob 存在时会出现 404?
- coordinates - 使用openlayers计算2点之间的距离
- rest - REST API 在 janus 中被禁用
- c# - 是否可以在一行中确定字符串是否位于字符串数组中的任何位置?
- python - Numpy删除重复行而不考虑行元素的位置
- jmeter - 使用 JMeter 模拟获取网页
- assembly - 为什么 clang 要用这么长的代码序列来构建一个 64 位的常量?
- git - git 提交文件中的 '>8' 是什么意思?