在滚动实时CorePlot Scatterplot上更新X轴

时间:2012-06-01 13:49:32

标签: ios ipad core-plot

我正在尝试使用iOS 5.1在iPad上使用CorePlot 1.0实现实时散点图。事情很好地解决了几个问题和一个主要的例外 - 轴重绘。

当收集到足够的数据时,我会调整plotSpace中的范围:

CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(self.graphMinX)
                                                length:CPTDecimalFromFloat(self.graphRangeX)];    

当我这样做时,图表上的图调整就好像轴已经改变了但是轴没有调整 - 因此数据图正确显示在不正确的轴上。停止数据源后,轴将正确更新5秒。

我已经从CorePlot iOS Plot Gallery查看了RealTimePlot(RTP)中的代码,但我找不到任何重要的差异(尽管肯定存在)。

我的代码与RTP之间存在一个区别:

我在后台GCD队列中捕获新数据,然后将其附加到[NSNotificationCenter defaultCenter]

中的自定义通知中进行“分发”

更新 体系结构层次结构的简化视图如下所示:

  • SplitViewController
    • DetailViewController
      • TreatmentGraph对象(管理CPTXYGraph
        • [{1}}个对象的集合(每个对象管理一个TreatmentChannel

CPTXYPlot有一个数据通知观察者,如下所示:

DetailViewController

(请注意,我强制使用GCD帖子将数据重新加载到UI队列 - RTP中的示例似乎不需要这样)这是一个红旗,但是什么?

- (void)dataArrived:(NSNotification *)notification { FVMonitoredSignal *sig = [notification object]; NSValue *currValue = [sig.dataPoints lastObject]; CGPoint point = [currValue CGPointValue]; [self.treatmentGraph addPoint:point toChannelWithIdentifier:sig.signalName]; dispatch_async(dispatch_get_main_queue(), ^{ [self.graphHostingView.hostedGraph reloadData]; }); return; } 内,我们检查是否需要进行X轴调整,并将数据分派到相应的TreatmentGraph

TreatmentChannel

我的猜测是在主队列空闲之前轴没有更新,但由于我已经在新数据到达时强制重新加载,我很困惑为什么轴重绘不会发生。

- (void)addPoint:(CGPoint)point toChannelWithIdentifier:(NSString *)identifier { // Check for a graph shift if (point.x >= (self.graphMinX + self.graphRangeX)) { [self shiftGraphX]; } FVTreatmentChannel *channel = [self.channels objectForKey:identifier]; [channel addPoint:point]; return; } - (void)shiftGraphX { CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace; plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(self.graphMinX) length:CPTDecimalFromFloat(self.graphRangeX)]; } 接受这样的新数据:

TreatmentChannel

请注意,我正在使用- (void)addPoint:(CGPoint)point { [self.plotData addObject:[NSValue valueWithCGPoint:point]]; // cache it [self.plot insertDataAtIndex:self.plotData.count-1 numberOfRecords:1]; [self.plot reloadData]; } 添加新数据,并专门在-insertDataAtIndex:numberOfRecords:上调用-reloadData。这不会导致显示更新 - 直到CPTXYPlot中的数据通知处理程序中调用-reloadData才会显示更新。

问题:

  1. 我可以做些什么来使我的轴更及时更新?
  2. 除非我在数据到达时强行重新加载,否则为什么我的图表上没有绘图?任何线索?
  3. 通过确保对轴和/或图表空间的任何更新被包装以将它们放回GCD主队列来解决第1项。

    第2项是通过将对DetailViewController的来电包裹起来解决的,因此可以删除许多困扰我的-insertDataAtIndex:numberOfRecords:来电。

    故事的道德:考虑与CorePlot的交互等同于UIKit调用 - 确保它们都发生在主队列上。

1 个答案:

答案 0 :(得分:2)

  1. 无论何时绘图空间范围发生变化,轴都应重新标记并重绘。您何时根据新数据更新绘图空间?

  2. 你必须告诉情节,新数据是可用的。 -reloadData是一种方法,尽管对于这个应用程序,有更快的方法来做到这一点。实时绘图示例使用-insertDataAtIndex:numberOfRecords:-deleteDataInIndexRange:添加新点并删除滚出视图的点。这比每次更改时重新加载绘图的所有数据都要快。如果您有多个绘图,则在图表上调用-reloadData而不是受影响的绘图会更慢,因为它将重新加载所有绘图的数据。