Background:
The graphs that I've added to my app plot data in realtime. Data is sent to the app over a BLE connection and I plot the data on the graph as it comes in. The graphs start off with no data in them. All of the graphs plot similar sets of data, just for different components, so if I can get one working they should all work.
A graph has two line series that plot readings from two different sensors. The are two y-axes on the graph, each plotting the reading from one of the sensors. The x-axis is a time series, it's values should correspond with when the readings come in over BLE.
Currently, I can't seem to get the graph to plot new points when I add a new data. If I pre-populate my data array with datapoints before i create the datasource helper object, those points are plotted on the graph correctly. Here is the relevant code for one of the line series:
@objcMembers class DataModel: NSObject { var date: Date! var value: NSNumber! init(date: Date, value: NSNumber) { self.date = date self.value = value } }
When data comes in for one of the plots, it's stored as a DataModel object and added to an array like:
var oilTempReadings: [DataModel] = []
These are the class types I'm using for my axes and data series:
var xAxisTemp: IGCategoryDateTimeXAxis! var yAxisTemp: IGNumericYAxis! var temperatureLineSeries: IGLineSeries! var temperatureDataSource: IGCategoryDateSeriesDataSourceHelper!
And this is how I'm setting up my datasource helper:
temperatureDataSource = IGCategoryDateSeriesDataSourceHelper.init(data: bleManager.coolantTempReadings, valuePath: "value", andDatePath: "date") temperatureLineSeries.yAxis = yAxisTemp temperatureLineSeries.xAxis = xAxisTemp temperatureLineSeries.dataSource = temperatureDataSource graph.add(xAxisTemp) graph.add(yAxisTemp) graph.addSeries(temperatureLineSeries)
If I have test data in the coolantTempReadings array at this point, they are immediately populated in the graph when I add the graph to the subview. However, when new data comes in and I try to insert it into the graph, it doesn't show up. This is how I'm trying to insert the new data:
graph.insertItem(at: bleManager.coolantTempReadings.count - 1, with: temperatureDataSource)
Any ideas why the graphs aren't updating with the new data?
OK thanks, glad I'm not crazy. I'll try it out using the refresh() method with fewer data points.
Could've sworn this worked in earlier versions of Swift, but you're right, the data in the DSH and chartData arrays are not the same. You might have to resort to calling refresh on the chart instead of insert.
I've rewritten my code from your example, and now the graph is adding new points. However, all of the values are 0.
Graph creation:
graph = IGChartView.init(frame: CGRect.init(x: 0, y: 0, width: container.frame.width, height: container.frame.height)) graph.autoresizingMask = [UIViewAutoresizing.flexibleHeight, UIViewAutoresizing.flexibleWidth] graph.theme = IGChartDefaultThemes.defaultTheme() graph.gridMode = IGGridMode.behindSeries graph.zoomDisplayType = IGChartZoom.horizontal temperatureDataSource = IGCategoryDateSeriesDataSourceHelper.init(data: bleManager.coolantTempReadings, valuePath: "value", andDatePath: "date") doorDataSource = IGCategoryDateSeriesDataSourceHelper.init(data: bleManager.coolantDoorReadings, valuePath: "value", andDatePath: "date") graph.delegate = self graph.addSeries(forType: IGLineSeries.self, usingKey: "tempSeries", with: temperatureDataSource, firstAxisKey: "x", secondAxisKey: "tempY") graph.addSeries(forType: IGLineSeries.self, usingKey: "doorSeries", with: doorDataSource, firstAxisKey: "x", secondAxisKey: "doorY") let tempY: IGNumericYAxis = graph.findAxis(byKey: "tempY") as! IGNumericYAxis tempY.labelsLocation = IGAxisLabelsLocation.outsideLeft tempY.minimum = 0 tempY.maximum = 140 let doorY: IGNumericYAxis = graph.findAxis(byKey: "doorY") as! IGNumericYAxis doorY.labelsLocation = IGAxisLabelsLocation.outsideRight doorY.minimum = 0 doorY.maximum = 100 doorY.majorStrokeThickness = 0 graphContainer.addSubview(graph)
When new values come in:
graph.insertItem(at: bleManager.coolantDoorReadings.count - 1, with: doorDataSource)
I'm logging the values to the console, they aren't 0. It seems that the datasources values aren't getting updated when their associated data object is. Maybe it's an objective-c to swift translation issue?
Separate Y axes shouldn't make a difference. This new code will put 2 separate Y axes in the chart, each with a different range.
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. _chartData = [[NSMutableArray alloc]init]; _dsh1 = [[IGCategoryDateSeriesDataSourceHelper alloc]initWithData:_chartData valuePath:@"value1" andDatePath:@"date1"]; _dsh2 = [[IGCategoryDateSeriesDataSourceHelper alloc]initWithData:_chartData valuePath:@"value2" andDatePath:@"date2"]; _chart = [[IGChartView alloc]initWithFrame:self.view.bounds]; _chart.delegate = self; [_chart addSeriesForType:[IGLineSeries class] usingKey:@"series1" withDataSource:_dsh1 firstAxisKey:@"x" secondAxisKey:@"y1"]; [_chart addSeriesForType:[IGLineSeries class] usingKey:@"series2" withDataSource:_dsh2 firstAxisKey:@"x" secondAxisKey:@"y2"]; IGNumericYAxis *y1 = (IGNumericYAxis*)[_chart findAxisByKey:@"y1"]; y1.labelsLocation = IGAxisLabelsLocationOutsideLeft; y1.minimum = 0; y1.maximum = 10; IGNumericYAxis *y2 = (IGNumericYAxis*)[_chart findAxisByKey:@"y2"]; y2.labelsLocation = IGAxisLabelsLocationOutsideRight; y2.minimum = 10; y2.maximum = 100; y2.majorStrokeThickness = 0; [self.view addSubview:_chart]; _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerTick) userInfo:nil repeats:YES]; } -(void)timerTick { ChartData *obj = [[ChartData alloc]init]; obj.date1 = obj.date2 = [NSDate new]; obj.value1 = arc4random()%10; obj.value2 = arc4random()%90 + 10; [_chartData addObject:obj]; NSInteger index = _chartData.count-1; [_chart insertItemAtIndex:index withSource:_dsh1]; [_chart insertItemAtIndex:index withSource:_dsh2]; }
It looks like your example is using the same x and y axes for both series, whereas my chart is plotting the values for each series on its own y-axis (one is a value and one is a percentage, so they don't use the same scale). So maybe that's why yours works and mine doesn't?
Is there something special I need to do when using different axes? I tried creating them with separate y-axes but sharing the same x-axis, but then one of the line series just didn't show up at all, and the one that did get drawn still didn't update with new values.