How do I use getData() to plot a LineChart with ObjC PNChart library in Swift?

I am a newbie programmer and recently started learning Swift.

I am making a project in Swift and my intention is to plot a user-introduced signal function in the same View where the parameters are introduced (using a subView controlled by the class PNLineChart).

  • Swift - How do you DECIDE the optimal “Deployment Target” for your iOS app
  • UILabel auto resize on basis of text to be shown
  • iOS dismiss UIAlertView beforing showing another
  • How to call a method a.s.a.p. but at earliest in the next run loop iteration?
  • Breaking on unrecognized selector
  • CoreData and iCloud
  • The fact is that I installed PNChart library using CocoaPods, using a bridging header for the Objective C headers. The thing is that the way to use the clases and methods in ObjC is “translating” them to Swift syntax. I found that PNChart has a Swift implementation made by the author, but is not available by Pods (if someone knows how to put them into my project it will be helpful too).

    Well, the ObjC code to make the plot of an array given by the author in its wiki is the following:

    #import "PNChart.h"
    
    //For Line Chart
    PNLineChart * lineChart = [[PNLineChart alloc] initWithFrame:CGRectMake(0, 135.0, SCREEN_WIDTH, 200.0)];
    [lineChart setXLabels:@[@"SEP 1",@"SEP 2",@"SEP 3",@"SEP 4",@"SEP 5"]];
    
    // Line Chart No.1
    NSArray * data01Array = @[@60.1, @160.1, @126.4, @262.2, @186.2];
    PNLineChartData *data01 = [PNLineChartData new];
    data01.color = PNFreshGreen;
    data01.itemCount = lineChart.xLabels.count;
    data01.getData = ^(NSUInteger index) {
        CGFloat yValue = [data01Array[index] floatValue];
        return [PNLineChartDataItem dataItemWithY:yValue];
    };
    // Line Chart No.2
    NSArray * data02Array = @[@20.1, @180.1, @26.4, @202.2, @126.2];
    PNLineChartData *data02 = [PNLineChartData new];
    data02.color = PNTwitterColor;
    data02.itemCount = lineChart.xLabels.count;
    data02.getData = ^(NSUInteger index) {
        CGFloat yValue = [data02Array[index] floatValue];
        return [PNLineChartDataItem dataItemWithY:yValue];
    };
    
    lineChart.chartData = @[data01, data02];
    [lineChart strokeChart];
    

    So I tried to convert it to Swift, where:

    • inputSignal : UITextField! -> will be the textField where the user introduces the mathematical function (this is still under development)
    • other IBOutlet -> Parameters to set the function limits and the global chart limits
    • inputSignalLineChart: PNLineChart! -> connection of the subView to the ViewController
    • initSignalExample -> initial array to test the plotting
    • signalObtainedValues -> declaration of the PNLineChartData type

    Inside the viewDidLoad() function I am initiating an initial chart to test if it works in the View. The problem comes when I try to use the method getData() that is defined in the PNLineChartData class and I am not really able to translate it to a correct Swift code.

    My understanding is that getData has as input an UInteger called index (I think it will select the individual data, but I do not see it declared anywhere :-/) and as output it returns a PNLineChartDataItem(). As I see in the ObjC code, the way to do this is somewhat like PNLineChartDataItem(y: CGFloat) so I suppose that I can do the code as I show you below:

    import UIKit
    
    
    class ViewController: UIViewController, PNChartDelegate{
    
    
        @IBOutlet weak var inputSignal: UITextField!
    
        @IBOutlet weak var initialTimeInputSignal: UITextField!
    
        @IBOutlet weak var finalTimeInputSignal: UITextField!
    
        @IBOutlet weak var initialGlobalTime: UITextField!
        @IBOutlet weak var finalGlobalTime: UITextField!
    
        @IBOutlet weak var inputSignalLineChart: PNLineChart!
    
        let screenWidth = UIScreen.mainScreen().bounds.size.width
        let screenHeight = UIScreen.mainScreen().bounds.size.height
        let initSignalExample = [0.0, 1.0, 1.0, 1.0, 0.0]
        let signalObtainedValues: PNLineChartData!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            view.backgroundColor = UIColor.cyanColor()
    
            inputSignalLineChart.delegate = self
            inputSignalLineChart.frame = CGRectMake(0, 135.0, screenWidth, screenHeight)
            inputSignalLineChart.backgroundColor = UIColor.whiteColor()
            inputSignalLineChart.setXLabels(["0","1","2","3","4"], withWidth: 1)
            //signalObtainedValues.color = UIColor.greenColor()
            //signalObtainedValues.itemCount = UInt(inputSignalLineChart.xLabels.count)
    
            signalObtainedValues.getData(UInt(index)) = { PNLineChartDataItem(y: CGFloat(initSignalExample[index]))
    
            }
    
            //inputSignalLineChart.chartData = [signalObtainedValues]
            inputSignalLineChart.strokeChart()
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
    
    }
    

    Trying and trying I only get the error: Cannot assign to the result of this expression, in the getData() line. So I think this is for the syntax of the code I have made in Swift. Has anyone any idea of how to do this and correctly draw the chart in the subview? Any answer or helpful tip will be appreciated. Thank you!

    4 Solutions Collect From Internet About “How do I use getData() to plot a LineChart with ObjC PNChart library in Swift?”

    Maybe this can be written in closure like the following:

    signalObtainedValues.getData() = {
        index in
        let yValue: CGFloat = initSignalExample[UInt(index)]
        return PNLineChartDataItem(y: yValue)
    }
    

    I finally got a solution for the problem. The code that works for me is the following:

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    
        view.backgroundColor = UIColor.cyanColor()
    
        playButton.layer.backgroundColor = UIColor.whiteColor().CGColor
        playButton.layer.cornerRadius = 5
    
        let initSignalExample = [0.0, 1.0, 2.0, 1.0, 0.0]
    
    
        lineChartSubView.frame = CGRectMake(0, 0, screenWidth, screenHeight)
        lineChartSubView.backgroundColor = UIColor.whiteColor()
        lineChartSubView.setXLabels(["0","1","2","3","4"], withWidth: 1)
        lineChartSubView.showCoordinateAxis = true
        lineChartSubView.showLabel = true
        lineChartSubView.delegate = self
    
        var signalObtainedValues = PNLineChartData()
    
        signalObtainedValues.color = UIColor.greenColor()
        signalObtainedValues.itemCount = UInt(initSignalExample.count)
        signalObtainedValues.getData = ({(index: UInt) -> PNLineChartDataItem in
            var yValue:CGFloat = CGFloat(initSignalExample[Int(index)])
            var item = PNLineChartDataItem(y: yValue)
            return item
        })
    
        lineChartSubView.chartData = [signalObtainedValues]
        lineChartSubView.strokeChart()
    
    }
    

    Now the problem is that the graph does not fit in the subview, but maybe I will open another question since the original post is solved.
    Thank you very much!

    How about this?

    signalObtainedValues.getData = ({(index: Int) -> PNLineChartDataItem in
    var yValue:CGFloat = signalObtainedValues[index]
    var item = PNLineChartDataItem(y: yValue)
    return item})
    

    I think the problem is that you forgot to add subview, the graph did not show.

    lineChartSubView.chartData = [signalObtainedValues]
    lineChartSubView.strokeChart()
    
    self.view.addSubview(lineChartSubView)