2

I'm using the Macaw framework for my charts. There's only one problem that if it the first time shows the "X" chart, it will always(until closing app) show the "X" chart. But the data is changing(I saw it in the debugger).

Here is the snippet of my "DahlichViewController".

class DahlichViewController: UIViewController {
    
@IBOutlet private var chartView: MacawChartView!
@IBOutlet weak var start: UIButton!
    
override func viewDidLoad() {
    super.viewDidLoad()
    chartView.backgroundColor = .clear
    chartView.contentMode = .scaleAspectFit
}

@IBAction func startPressed(_ sender: UIButton) {
    chartView.updateData(newData: createData())
    chartView.playAnimations()
}

And here's my MacawChartView.

import Foundation
import Macaw

class MacawChartView: MacawView {
    
    static var chartData = createData()
    
    static let maxValue              = 60
    static let maxValueLineHeight    = 18
    static let lineWidth: Double     = 275
    
    static let dataDivisor             = Double(maxValue/maxValueLineHeight)
    static let adjustedData: [Double]  = chartData.map({$0.percentage / dataDivisor})
    static var animations: [Animation] = []
    
    public func updateData(newData : [ElectionBrain])
    {
        MacawChartView.chartData = newData
        updateDisplay()
    }

    public func updateDisplay()
    {
        let chart = MacawChartView.createChart()
        self.node = Group(contents: [chart])
    }
    
    static func createChart() -> Group {
        var items: [Node] = addYAxisItems() + addXAxisItems()
        items.append(createBars())
        
        return Group(contents: items, place: .identity)
    }
    
    private static func addYAxisItems() -> [Node] {
        let maxLines            = 6
        let lineInterval        = Int(maxValue / maxLines)
        let yAxisHeight: Double = 200
        let lineSpacing: Double = 30
        
        var newNodes: [Node]    = []
        
        for i in 1...maxLines {
            let y = yAxisHeight - (Double(i) * lineSpacing)
            
            let valueLine = Line(x1: -5, y1: y, x2: lineWidth, y2: y).stroke(fill: Color.white.with(a: 0.10))
            let valueText = Text(text: "\(i * lineInterval)", align: .max, baseline: .mid, place: .move(dx: -10, dy: y))
            valueText.fill = Color.white
            
            newNodes.append(valueLine)
            newNodes.append(valueText)
        }
        
        let yAxis = Line(x1: 0, y1: 0, x2: 0, y2: yAxisHeight).stroke(fill: Color.white.with(a: 0.25))
        newNodes.append(yAxis)
        
        return newNodes
    }
    
    private static func addXAxisItems() -> [Node] {
        let chartBaseY: Double = 200
        var newNodes: [Node]   = []
        
        
        for i in 1...adjustedData.count {
            let x = (Double(i) * 50)
            let valueText = Text(text: chartData[i - 1].version, align: .max, baseline: .mid, place: .move(dx: x, dy: chartBaseY + 15))
            valueText.fill = Color.white
            newNodes.append(valueText)
        }
        
        let xAxis = Line(x1: 0, y1: chartBaseY, x2: lineWidth, y2: chartBaseY).stroke(fill: Color.white.with(a: 0.25))
        newNodes.append(xAxis)
        
        return newNodes
    }
    
    private static func createBars() -> Group {
        let fill  = LinearGradient(degree: 90, from: Color(val: 0xfff264), to: Color(val: 0xd69c00).with(a: 0.33))
        let items = adjustedData.map { _ in Group() }
        
        animations = items.enumerated().map { (i: Int, item: Group) in
            item.contentsVar.animation(delay: Double(i) * 0.1 ) { t in
                let height = adjustedData[i] * t * 10
                let rect   = Rect(x: Double(i) * 50 + 25, y: 200 - height, w: 30, h: height)
                return[rect.fill(with: fill)]
            }
        }
        
        return items.group()
    }
    
     func playAnimations() {
        MacawChartView.animations.combine().play()
    }

}

I declared my createData() function as global function(Not in VC). The problem is that data is changing but the chart doesn't. It all time shows the same chart.

Sam
  • 105
  • 1
  • 9
  • hope i saw that right.. each time you updateData, you trigger updateDisplay and in there you create the chart new with MacawChartView.createChart(). – Ol Sen Aug 02 '20 at 13:32
  • Yes, and each time data changes but the chart doesn't. – Sam Aug 02 '20 at 13:36
  • what happens when you comment out `// updateDisplay()` ? – Ol Sen Aug 02 '20 at 13:45
  • When I comment out it doesn't show even chart. – Sam Aug 02 '20 at 13:55
  • win win situation in swift, game over. It becomes so syntax sugary that you can't see the obvious, so throwing some classic questions in. Call to super? newNodes + newNodes, function parameters are adding them or overwriting? Why is Group used here? Does MacawView inherit from UIView/NSView/NSObject? – Ol Sen Aug 02 '20 at 16:57
  • where is Group(contents: items, place: .identity) defined? [apple doc swiftui](https://developer.apple.com/documentation/swiftui/group) – Ol Sen Aug 02 '20 at 17:05
  • I'm trying to do like this: stackoverflow.com/questions/61905079/. What you answered that are default implementation of that class. – Sam Aug 03 '20 at 06:12
  • 1
    @Sam - are you updating `adjustedData` each time? That's what you're displaying, not `chartData` – Russell Aug 04 '20 at 08:45
  • @Ohh that's true. Thank you so much. – Sam Aug 04 '20 at 08:51

2 Answers2

1

@Russel give me good advice. The problem was that I didn't update the adjustedData which truly updates the chart. I added this code in updateDisplay and it has worked.

        MacawChartView.adjustedData = MacawChartView.chartData.map({$0.percentage / MacawChartView.dataDivisor})
Sam
  • 105
  • 1
  • 9
0

Try calling setNeedsLayout() at the end of your updateDisplay() function.