2010-09-03 63 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的分辨率为100ms左右,但我没有自己测试(可能是错误的)。这种分辨率当然不能平稳上升。 – materialvision 2010-09-03 06:20:52

+0

你说得对,苹果的文档说了大约50-100毫秒。确切的分辨率还取决于你的运行循环中发生了什么。我会尝试计时器,看看它是否足够好。否则,你可能不得不使用另一个线程。 – Sven 2010-09-03 06:31:57

+0

是的,那种时间间隔不适用于音高,因为它需要非常平滑。所以我需要继续研究线程。 。 。 – materialvision 2010-09-03 06:41:24

1

不要使用while循环;它阻止了其他一切。使用计时器和状态机。计时器可以按照您想要更改的速率调用状态机。状态机可以查看最后一个斜坡值和最后一个按钮点击的时间(或者甚至是一系列UI事件时间),并决定在下一个时间段内是否需要增加音量(逻辑通常只是一堆if和select/case语句,如果控制算法不适合一个好的表)。然后状态机可以调用处理实际声级的对象或例程。

+0

谢谢,但正如你在上面关于NSTimer的其他答案的讨论中可以看到的那样,它没有足够大的分辨率来处理音调(这将导致非常可听的步骤)。我可能需要在一个单独的线程或类似的东西中运行状态机。 – materialvision 2010-09-03 06:45:19

1

看看NSOperationConcurrency Programming Guide。您可以先开始操作增加音高并存储操作对象。在第二次通话中,您可以拨打[operation cancel]停止最后一次操作。开始第二个操作即减少音调并存储新的对象。

顺便说一句:你现在正在做的是非常糟糕的,因为你“阻止主线程”。需要一些时间的计算不应该直接执行。您应该也可以看看NSTimer,让您的代码独立于处理器的速度。

+0

谢谢我将研究NSOperation,但是我可能仍然需要某种多线程,正如您从NSTimer不够快的其他答案中可以看到的那样。 – materialvision 2010-09-03 06:46:46

+0

@materialvision:如果你需要线程,NSOperation是最简单的方法。 – Chuck 2010-09-03 07:50:57

+0

@materialvision:NSOperation *是一种多线程的方式。操作队列为其上的每个操作生成一个新线程。 – JeremyP 2010-09-03 08:39:58

相关问题