【发布时间】:2012-06-01 13:49:31
【问题描述】:
我正在尝试在装有 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)
-
- [收集]
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: 仅添加新数据并专门在CPTXYPlot 上调用-reloadData。这不会导致显示更新 - 直到在 DetailViewController 的数据通知处理程序中调用 -reloadData 后,我才会获得显示更新。
问题:
- 我可以做些什么来使我的轴更及时地更新?
- 有什么线索可以解释为什么除非我在数据到达时强制重新加载,否则我的图表上没有图表?
通过确保对轴和/或绘图空间的任何更新都进行包装以将它们放回 GCD 主队列来解决第 1 项。
第 2 项已通过包装对 -insertDataAtIndex:numberOfRecords: 的调用得到解决,从而可以删除许多困扰我的 -reloadData 调用。
故事的寓意:考虑与 UIKit 调用等效的 CorePlot 交互 - 确保它们都发生在主队列上。
【问题讨论】: