Я хочу иметь возможность обновлять/перезагружать ScatterPlot на устройствах iOS во время выполнения. Чтобы быть конкретным, я записываю аудиовход, делаю некоторые забавные вещи и ставил результат как простое значение NSNumber в массив. Всякий раз, когда это происходит, reloadData вызывается на графике, который я хочу обновить, но, к сожалению, ничего не происходит. В принципе, я делаю то же, что описано в ответе здесь: real time plotting on iPhone using core plot?. Это просто не работает, поэтому я предполагаю, что совершил какую-то глупую ошибку.Core-Plot: вызов reloadData на графике или графике изнутри блока не работает
Это соответствующий метод:
-(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;
}
}
}
Х Squared земля не имеет никакого отношения к моим потребностям на данный момент, это просто ссылка. LivePlot - это тот, который мне нужен и который нужно обновить. _plotIndizesAndVolume - это NSMutableArray, в котором хранятся мои значения. Он содержит 500 элементов, все из которых инициализируются с помощью [NSNumber numberWithFloat: 0.0f] в начале моего выполнения. Участок имеет также 500 индексов, поэтому мы не выходим за пределы или что-то еще.
Код исполняется отлично, метод вызывается, оператор printf работает и корректно отображает поплавки, план просто не обновляется.
Я также попытался
if (index < [_plotIndizesAndVolume count]) {
return [NSNumber numberWithFloat:[_plotIndizesAndVolume objectAtIndex:index]];
} else {
return [NSNumber numberWithFloat:0.0f];
}
, не имея 500 0.0fs в массиве, так что я просто получить доступ к значениям по-разному от 0.0f. Это, конечно, лучше, это просто не работает.
Любые идеи?
Update 1:
Если я заполняю _plotIndizesAndVolume с просто случайными числами в начале моего заявления, сюжет совершенно следует за этими числами.
Если I printf в методе, я могу отлично прочитать обновленные значения после того, как на сюжет вызывается перезагрузка.
Однако эти обновленные значения не показаны на графике. Сюжет остается таким, как после вызова -reloadData на нем, независимо от того, какие значения были изменены в _plotIndizesAndVolume-Array.
Таким образом, от того, что я могу видеть: я могу получить доступ к массиву правильно, я могу обновить и прочитать новые значения правильно, сюжет по-прежнему остается неизменным и не меняется. Я смущен. Вероятно, я все-таки совершил какую-то случайную глупую ошибку, я просто этого не вижу.
Update2:
Ну, кажется, что моя проблема не сама reloadData, но откуда я это называю. Еще один контекст: я использую новокаин для измерения децибел через микрофон устройства. Это прекрасно работает. Затем я хочу визуализировать часть измеренного дБ на графике через corePlot (который я описал выше). Я получил метод под названием startMeasuring
, который я называю somehen, а затем - очевидно - начните измерять децибел. Всякий раз, когда это происходит, я помещаю измеренное значение 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 правильно вызывается и значения корректно обновляются.
Update 3:
Если я позвоню reloadData
где-то еще во время измерения, обновления графа просто отлично, и в соответствии с, что находится в _plotIndizesAndVolume
. Он просто не обновляется, если я вызываю его изнутри блока (даже если я вызываю другой метод изнутри блока, который в свою очередь вызывает reloadData
). Тем не менее, мне нужно обновление в реальном времени. Я предполагаю, что я мог бы перезагрузить сюжет один раз каждые x miliseconds (собираюсь попробовать это дальше), мне все еще интересно, почему это не работает в первую очередь.
Обновление 4: Как принято в обновлении 3, если я звоню reloadData
откуда-то через NSTimer, он делает то, что я хочу, чтобы он делал. Почему я не могу назвать это изнутри блока?
Это не связано с сюжетом не появляется, но вы должны вернуться '[_plotIndizesAndVolume objectAtIndex: индекс] 'непосредственно, вместо того, чтобы преобразовать его в float и обратно в' NSNumber'. Он будет работать быстрее и сделает ваш код более удобным для чтения. –
Являются ли значения «xRange» и «yRange» для графика, чтобы данные попадали внутрь диапазонов? Например, с 500 точками данных, «xRange» должно иметь местоположение -10 и длину 100 для соответствия всем точкам. –
@EricSkroch NSNumber-> float-> Преобразование NSNumber было только я пытаюсь выяснить, есть ли ошибка в том, как код обрабатывает объект массива (поскольку objectAtIndex: возвращает id), что я не мог себе представить все, но я хотел попробовать любую возможность, даже те, кого я считаю глупыми. О xRange: не должно ли это быть значительным для «показа» частей сюжета? Неважно, какие части сюжета я показываю, ничего не меняется. Или я ошибаюсь? – Aerius