3

我希望能够在运行时更新/重新加载 iOS 设备上的 ScatterPlot。具体来说,我记录音频输入,做一些有趣的事情,并将结果作为一个简单的 NSNumber 值放入一个数组中。每当发生这种情况时,都会在我要更新的 Plot 上调用 reloadData,但遗憾的是,完全没有任何反应。基本上,我做的和这里的答案中描述的一样:real time plotting on iPhone using core plot? . 它只是不起作用,所以我认为我犯了一些愚蠢的错误。

这是相关的方法:

-(NSNumber *) numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index {

    double val = (index/5.0) -10;

    if (fieldEnum == CPTScatterPlotFieldX) {
        return [NSNumber numberWithDouble:val];
    } else {
        if ([plot.identifier isEqual: @"X Squared Plot"]) {
            return [NSNumber numberWithDouble:10-(0.25*val*val)];
        } else if( [plot.identifier isEqual:@"LivePlot"]) {
            if (!_isMeasuring) {
                return [NSNumber numberWithFloat:0.0f];
            } else {
                printf("%f", [[_plotIndizesAndVolume objectAtIndex:index] floatValue]);
                return [NSNumber numberWithFloat:[[_plotIndizesAndVolume objectAtIndex:index] floatValue]];
            }
        } else {
            return 0;
        }
    }
}

X Squared Plot 目前与我的需求无关,它只是一个参考。LivePlot 是我需要并想要更新的。_plotIndizesAndVolume 是我存储我的值的 NSMutableArray。它有 500 个元素,所有这些元素在我执行开始时都用 [NSNumber numberWithFloat:0.0f] 初始化。Plot 也有 500 个 indizes,因此我们不会越界或其他任何事情。

代码执行良好,方法被调用,printf 语句工作并正确显示浮点数,Plot 只是没有更新。

我也试过

if (index < [_plotIndizesAndVolume count]) {
    return [NSNumber numberWithFloat:[_plotIndizesAndVolume objectAtIndex:index]];
} else {
    return [NSNumber numberWithFloat:0.0f];
}

数组中没有 500 个 0.0fs,所以我只是访问与 0.0f 不同的值。这当然更好,它也不起作用。

有任何想法吗?

更新1:

  • 如果我在应用程序开始时仅用随机数填充 _plotIndizesAndVolume,则绘图完全遵循这些数字。

  • 如果我在方法中使用 printf,一旦在绘图上调用了 reload,我就可以完美地读取更新的值。

  • 但是,这些更新的值不会显示在图中。无论 _plotIndizesAndVolume-Array 中的哪些值发生变化,绘图都保持在对其调用 -reloadData 后的状态。

因此,据我所见:我可以正确访问数组,可以正确更新和读取新值,绘图仍然保持不变并且不会改变。我很困惑。可能我仍然犯了一些随机的愚蠢错误,我只是没有看到它。

更新2:

好吧,似乎我的问题不是 reloadData 本身,而是我从哪里调用它。更多背景信息:我正在使用 novocaine 通过设备麦克风测量分贝。这工作正常。然后,我想通过 corePlot(我在上面描述过)在图表中可视化部分测量的 dB。我得到了一种方法startMeasuring,我有时会调用它,然后 - 显然 - 开始测量分贝。每当发生这种情况时,我都会将测量值 int_plotIndicesAndVolume并调用reloadData绘图。

该方法看起来像这样(并且大部分是直接从 novocain 示例中复制的):

-(void) startMeasuring {

    if (_isMeasuring) {
        return;
    }

    __weak ViewController * wself = self;

    self.ringBuffer = new RingBuffer(32768, 2);
    self.audioManager = [Novocaine audioManager];

    // MEASURE SOME DECIBELS!
    // ==================================================
    __block float dbVal = 0.0;
    __block int count = 0;
    __block int limiter = 0;
    [self.audioManager setInputBlock:^(float *data, UInt32 numFrames, UInt32 numChannels) {

        vDSP_vsq(data, 1, data, 1, numFrames*numChannels);
        float meanVal = 0.0;
        vDSP_meanv(data, 1, &meanVal, numFrames*numChannels);

        float one = 1.0;
        vDSP_vdbcon(&meanVal, 1, &one, &meanVal, 1, 1, 0);
        dbVal = dbVal + 0.2*(meanVal - dbVal);

        float reducedVal = (dbVal + 66.0f)/3;

        if (!wself.measuringPaused && limiter > 10) {
            [wself.plotIndizesAndVolume replaceObjectAtIndex:count withObject:[NSNumber numberWithFloat:reducedVal]];
            [[wself.graph plotWithIdentifier:@"LivePlot"] reloadData];
            limiter = -1;
            ++count;
        }
        ++limiter;

    }];

    [self.audioManager play];

    _isMeasuring = true;

}

reloadData从测量块内调用。我不太了解使用块,我只是假设我可以做到这一点。但是,如果我尝试更改数组中的数据,然后从其他地方手动重新加载绘图,它会起作用并且绘图会相应地更新。问题是否与我在块内调用方法有关?

即使这样,我仍然不确定为什么它不起作用,因为 printf 语句可以完美运行 - 所以我假设 updateData 方法被正确调用并且值被正确更新。

更新 3:

如果我reloadData在测量过程中从其他地方打电话,图表会更新得很好,并且会根据_plotIndizesAndVolume. 如果我从块内调用它,它根本不会更新(即使我从块内调用另一个方法,而该方法又调用reloadData)。但是,我需要实时更新。我想我也可以每 x 毫秒重新加载一次绘图(接下来会尝试),我仍然很好奇为什么它一开始就不起作用。

更新 4:正如更新 3 中所假设的,如果我reloadData通过 NSTimer 从其他地方调用,它会完全按照我的意愿执行。那为什么我不能从块内调用它呢?

4

2 回答 2

3

-reloadData从主线程调用(和任何其他 Core Plot 方法)。

于 2013-09-26T23:37:12.593 回答
2

可能您需要在计时器中更新绘图空间 x-range/y-range

CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;
[plotSpace scaleToFitPlots:[self.graph allPlots]];

CPTPlot *thePlot   = [self.graph plotWithIdentifier:kIdentifier];
[thePlot reloadData];
于 2014-12-08T16:45:35.643 回答