我正在尝试在装有 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
观察者,如下所示:
- (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;
}
(请注意,我使用 GCD 将数据强制重新加载到 UI 队列 - RTP 中的示例似乎不需要这样做)这是一个危险信号,但是什么?
在TreatmentGraph
我们检查是否需要调整 X 轴并将数据发送到适当的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
在数据通知处理程序中调用DetailViewController
我才获得显示更新。
问题:
- 我该怎么做才能使我的轴更及时地更新?
- 除非我在数据到达时强制重新加载,否则为什么我没有在图表上显示图表的任何线索?
通过确保对轴和/或绘图空间的任何更新都被包装以将它们放回 GCD 主队列来解决第 1 项。
第 2 项通过包装调用来解决,以-insertDataAtIndex:numberOfRecords:
允许删除许多-reloadData
困扰我的调用。
故事的寓意:考虑与 UIKit 调用等效的 CorePlot 交互 - 确保它们都发生在主队列上。