在 KLineViewController 開出的 volumeDataSet 會在 parent vc 推進來前就設定好。
所以我們直接在 KLine VC 裡面操作大盤量的 data 即可。
var volumeDataSet = [TwMarketTradingInfo]()
要讓文字轉成數字,要先開出 TwMarketTradingInfo 在 Charts 上用的屬性
import Foundation
struct TwMarketTradingInfo: Hashable {
let date: Date
let tradeVolumeString: String
let tradeValueString: String
let transactionString: String
let taiexString: String
let changeString: String
private var numberFormatter: NumberFormatter {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter
}
var value: Double? {
return numberFormatter.number(from: tradeValueString)?.doubleValue
}
var volume: Double? {
return numberFormatter.number(from: tradeValueString)?.doubleValue
}
var transaction: Double? {
return numberFormatter.number(from: transactionString)?.doubleValue
}
var taiex: Double? {
return numberFormatter.number(from: taiexString)?.doubleValue
}
var change: Double? {
return numberFormatter.number(from: changeString)?.doubleValue
}
}
先進入 ChartsAdapter,我們要讓 volumeDataList 轉成 BarChartData
/// 取得大盤量的 Data
private func getVolumeBarData(volumeDataList: [TwMarketTradingInfo]) -> BarChartData {
var barDataEntryList = [BarChartDataEntry]()
for (index, info) in volumeDataList.enumerated() {
let y = info.volume ?? 0
let dataEntry = BarChartDataEntry(x: Double(index), y: y)
barDataEntryList.append(dataEntry)
}
let dataSet = BarChartDataSet(entries: barDataEntryList)
dataSet.drawValuesEnabled = false //如果把數值也列出,圖會非常的雜亂,而且值可以設定在右邊
dataSet.axisDependency = .right //左方的軸已經設定給加權指數了,所以量的圖要設定在右邊的軸
let data = BarChartData(dataSet: dataSet)
return data
}
接著,修改 updateWithMALine 的接口,輸入參數要擴充 volumeDataList
//原來的接口
// func updateWithMALine(stockSticks: [StockKLine], combinedView: UIView) {
// 擴充 volumeDataList
func updateWithMALine(stockSticks: [StockKLine], volumeDataList: [TwMarketTradingInfo], combinedView: UIView) {
然後在實作 combinedData 後,加上 barData
func updateWithMALine(stockSticks: [StockKLine], volumeDataList: [TwMarketTradingInfo], combinedView: UIView) {
if let combinedView = combinedView as? CombinedChartView {
let ma5DataSet = getMALineData(stockSticks: stockSticks, range: 5, color: .blue)
let ma10DataSet = getMALineData(stockSticks: stockSticks, range: 10, color: .red)
let ma20DataSet = getMALineData(stockSticks: stockSticks, range: 20, color: .systemOrange)
let lineData = LineChartData(dataSets: [ma5DataSet, ma10DataSet, ma20DataSet])
let candleData = getCandleData(stockSticks: stockSticks)
let barData = getVolumeBarData(volumeDataList: volumeDataList)
let combinedData = CombinedChartData()
combinedData.lineData = lineData
combinedData.candleData = candleData
combinedData.barData = barData
combinedView.data = combinedData
// 這邊有優化空間,請讀者自行優化
let candleDataEntry = convert(stockStick: stockSticks)
let dataSet = convert(dataEntry: candleDataEntry)
updateMaxMin(combinedView, dataSet: dataSet)
let indexDateLabels = getIndexDateLabels(from: stockSticks)
updateXAxis(combinedView, indexDateLabels: indexDateLabels)
}
}
接下來,就去改 KLineViewController 的 setupCandleView()
private func setupCandleView() {
chartsAdapter.updateWithMALine(stockSticks: kLineDataSet, volumeDataList: volumeDataSet, combinedView: chartView)
}
出來的結果就像這樣子,還差了一點。
因為資料來源有告訴我們,當日漲還是跌,所以更好的表示,就是當那一天的大盤是漲的,Bar 就是紅色,反之就是綠色。
在 BarChartDataSet() 生出來之後,可以設定 [UIColor],去設定顏色。
再擴充 ChartsAdapter,讓這個物件可以得到每一根 bar 的顏色
private func getBarColors(volumeList: [TwMarketTradingInfo]) -> [UIColor] {
let colors = volumeList.map { info -> UIColor in
let change = info.change ?? 0
if change < 0 {
return UIColor.systemGreen
}
return UIColor.systemRed
}
return colors
}
然後,在從 getVolumeBarData 轉成 DataSet 之後,加上 colors,就完成了。
/// 取得大盤量的 Data
private func getVolumeBarData(volumeDataList: [TwMarketTradingInfo]) -> BarChartData {
var barDataEntryList = [BarChartDataEntry]()
for (index, info) in volumeDataList.enumerated() {
let y = info.volume ?? 0
let dataEntry = BarChartDataEntry(x: Double(index), y: y)
barDataEntryList.append(dataEntry)
}
let dataSet = BarChartDataSet(entries: barDataEntryList)
dataSet.drawValuesEnabled = false //如果把數值也列出,圖會非常的雜亂,而且值可以設定在右邊
dataSet.axisDependency = .right //左方的軸已經設定給加權指數了,所以量的圖要設定在右邊的軸
let colors = getBarColors(volumeList: volumeDataList) //加上顏色
dataSet.colors = colors
let data = BarChartData(dataSet: dataSet)
return data
}
Build 起來試試看。
我們得到了軟體工程師的日常禮物「有 bug!」
我們下一篇來解決這個 Charts 沒有照大腦中呈現的方式畫的狀況。