2010-09-03 1 views
1

Каков наилучший способ справиться с этой ситуацией на устройстве iPhone: моя программа увеличивает высоту звука между двумя значениями. Нажатая кнопка вызывает метод, который имеет цикл while, который выполняет масштабирование с небольшими приращениями. Это займет некоторое время, чтобы закончить. Тем временем пользователь нажал другую кнопку, вызывающую тот же метод. Теперь я хочу, чтобы цикл в первом вызове останавливался, а второй - в текущем состоянии. Вот что-то вроде того, что метод должен выглядеть следующим образом:Как обрабатывать методы класса, вызываемые снова до их завершения?

-(void)changePitchSample: (float) newPitch{ 
float oldPitch=channel.pitch; 
if (oldPitch>newPitch) { 
    while (channel.pitch>newPitch) { 
     channel.pitch = channel.pitch-0.001; 
    } 
} 
else if (oldPitch<newPitch) { 
    while (channel.pitch<newPitch) { 
     channel.pitch = channel.pitch+0.001; 
    } 
} 

}

Теперь, как лучше справиться с ситуацией, когда метод вызывается снова? Нужно ли мне какое-то мулитрование? Мне не нужны два процесса одновременно, поэтому кажется, что должно быть какое-то более простое решение, которое я не могу найти (будучи новым для этого языка).

Любая помощь очень ценится!

ответ

1

Вы не можете так сделать. Пока ваш цикл работает, события не будут обработаны. Поэтому, если пользователь нажимает кнопку снова, ничего не произойдет, пока ваш цикл не будет завершен. Кроме того, вы не можете контролировать скорость вашего пандуса. Я бы предложил использовать NSTimer. В вашем методе changePitchSample: вы где-то храните новый шаг (не перезаписывайте старый) и запускайте таймер, который срабатывает один раз. Когда срабатывает таймер, вы увеличиваете высоту тона и, если он меньше, чем новый шаг, вы перезапускаете таймер.

+0

Спасибо. Я где-то читал, что у NSTimer было разрешение 100 мс или около того, но я еще не тестировал его (возможно, это было неправильно). Разумеется, такая резолюция не сможет сделать плавный скат. – materialvision

+0

Вы правы, документация на яблоки говорит примерно о 50-100 мс. Точное разрешение зависит также от того, что еще происходит в вашем цикле запуска. Я попробую таймер и посмотрю, достаточно ли это. В противном случае вам, вероятно, придется использовать другой поток. – Sven

+0

Да, такой временной интервал не будет работать с шагом, так как он должен быть очень плавным. Поэтому мне тогда нужно будет заглянуть в поток. , , – materialvision

1

Не используйте цикл while; он блокирует все остальное. Используйте таймер и конечный автомат. Таймер может вызвать конечный автомат со скоростью, с которой вы хотите, чтобы все изменилось. Конечный автомат может посмотреть на последнее значение рампы и время последней нажатой кнопки (или даже массив времени событий пользовательского интерфейса) и решить, будет ли и как увеличить уровень громкости на следующем шаге (логика часто является просто кучей операторов if и select/case, если алгоритм управления не поддается красивой таблице). Затем конечный автомат может вызывать объект или подпрограмму, которая обрабатывает фактический уровень звука.

+0

Спасибо, но, как вы можете видеть в обсуждении другого ответа выше о NSTimer, он не имеет достаточно большого разрешения для работы с шагом (что приведет к очень слышимым шагам). Мне, вероятно, потребуется запустить конечный автомат в отдельном потоке или что-то в этом роде. – materialvision

1

Посмотрите на NSOperation и Concurrency Programming Guide. Вы можете сначала начать работу с увеличением высоты тона и также сохранить объект операции. Во втором вызове вы можете позвонить [operation cancel], чтобы остановить последнюю операцию. Начните вторую операцию, чтобы уменьшить шаг и сохранить новый объект.

Btw: То, что вы сейчас делаете, очень плохо, так как вы «блокируете основную нить». Вычисления, требующие некоторого времени, не должны выполняться напрямую. Вероятно, вы также должны взглянуть на NSTimer, чтобы сделать ваш код независимым от скорости процессора.

+0

Спасибо, я посмотрю на NSOperation, но мне, вероятно, все-таки понадобится многопоточность, как вы можете видеть из других ответов, касающихся NSTimer, недостаточно быстрого. – materialvision

+0

@materialvision: Если вам нужна потоковая передача, NSOperation - это самый простой способ сделать это. – Chuck

+0

@materialvision: NSOperation * - это способ многопоточности. Операционная очередь генерирует новый поток для каждой операции, которая находится на нем. – JeremyP

Смежные вопросы