如何在 Swift 中重新加载来自外部 API 的折线图数据?

Posted

技术标签:

【中文标题】如何在 Swift 中重新加载来自外部 API 的折线图数据?【英文标题】:How to reload Linechart Data which is coming from external API in Swift? 【发布时间】:2019-09-17 06:47:37 【问题描述】:

我在一个 ios 应用程序中工作,我从 API 检索数据并将其显示在 LineChart 中。正在以 JSON 格式检索数据。我还展示了正确显示数据的表格视图。但在 LineChart 的情况下,我遇到了问题。由于数据来自本质上是异步的 Alamofire 请求,因此在数据到来之前绘制图表。谁能建议我在这方面的最佳行动方案。

//
//  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
    
    
  

感谢您在这方面的支持。

编辑:

我以不同的方式完成了任务。我创建了一个单例类来存储我需要的值,并且图表在加载时获取数据。但对我来说,这不是最好的解决方案。所以等待某人的善意回复。

【问题讨论】:

【参考方案1】:

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

View Did 加载方法应该是这样的

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

            
        
    

【讨论】:

以上是关于如何在 Swift 中重新加载来自外部 API 的折线图数据?的主要内容,如果未能解决你的问题,请参考以下文章

从列表中选择并重新加载 Tableview Swift

如何在 Swift 中使用文件系统事件 API?

如何重新加载 UIPageViewController 以在 Swift 中重新加载其视图

Swift数组追加不适用于collectionView重新加载数据

如何在 swift 中重新加载 UICollectionReusableView 中的集合视图

如何在swift 3中重新加载没有动画的特定单元格?