3

実行時に iOS デバイスで ScatterPlot を更新/リロードできるようにしたいと考えています。具体的には、オーディオ入力を録音し、面白いことをして、結果を単純な NSNumber 値として配列に入れます。それが起こるたびに、更新したい Plot で reloadData が呼び出されますが、悲しいことに、まったく何も起こりません。基本的に、ここの回答で説明されているのと同じことを行います: core plot を使用して iPhone でリアルタイムにプロットしますか? . うまくいかないので、愚かな間違いを犯したと思います。

これは関連する方法です:

-(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 2乗プロットは、今のところ私のニーズには関係ありません。単なる参照です。LivePlot は私が必要とし、更新したいものです。_plotIndizesAndVolume は、値を格納する NSMutableArray です。500 個の要素があり、実行の開始時に [NSNumber numberWithFloat:0.0f] ですべて初期化されます。プロットには 500 のインディーズもあります。

コードは正常に実行され、メソッドが呼び出され、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 すると、プロットでリロードが呼び出されると、更新された値を完全に読み取ることができます。

  • ただし、これらの更新された値はプロットに表示されません。_plotIndizesAndVolume-Array でどの値が変更されても、プロットは -reloadData を呼び出した後も元のままです。

したがって、私が見ることができることから、配列に適切にアクセスでき、新しい値を適切に更新および読み取ることができ、プロットは同じままで変化しません。よくわかりません。おそらく、私はまだランダムな愚かな間違いを犯したのでしょう。

アップデート2:

まあ、私の問題はreloadData自体ではなく、私がそれを呼び出すところからのようです。もう少しコンテキスト:デバイスのマイクを介してデシベルを測定するためにノボカインを使用しています。これはうまくいきます。次に、測定した dB の一部を corePlot (上記で説明) を使用してグラフで視覚化します。私はstartMeasuringいつか呼び出すメソッドを取得し、それから明らかにデシベルの測定を開始しました。それが起こるたびに、測定値をintに入れてプロット_plotIndicesAndVolumeを呼び出します。reloadData

メソッドは次のようになります (大部分はノボカインの例から直接コピーされています)。

-(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ミリ秒ごとに1回プロットをリロードできると思います(次にそれを試します)が、そもそもなぜそれが機能しないのかについてまだ興味があります。

更新 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 に答える