我正在尝试使用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]
更新 体系结构层次结构的简化视图如下所示:
TreatmentGraph
对象(管理CPTXYGraph
)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
才会显示更新。
问题:
通过确保对轴和/或图表空间的任何更新被包装以将它们放回GCD主队列来解决第1项。
第2项是通过将对DetailViewController
的来电包裹起来解决的,因此可以删除许多困扰我的-insertDataAtIndex:numberOfRecords:
来电。
故事的道德:考虑与CorePlot的交互等同于UIKit调用 - 确保它们都发生在主队列上。
答案 0 :(得分:2)
无论何时绘图空间范围发生变化,轴都应重新标记并重绘。您何时根据新数据更新绘图空间?
你必须告诉情节,新数据是可用的。 -reloadData
是一种方法,尽管对于这个应用程序,有更快的方法来做到这一点。实时绘图示例使用-insertDataAtIndex:numberOfRecords:
和-deleteDataInIndexRange:
添加新点并删除滚出视图的点。这比每次更改时重新加载绘图的所有数据都要快。如果您有多个绘图,则在图表上调用-reloadData
而不是受影响的绘图会更慢,因为它将重新加载所有绘图的数据。