我使用Objective C创建了一个鼓音序器。我希望滑块控制速度。目前,一切正常,每个步骤之间的间隔由以下方式控制:
while (self.running)
{
// sleep until the next step is due
[NSThread sleepUntilDate:time];
// update step
int step = self.step + 1;
// wrap around if we reached NUMSTEPS
if (step >= NUMSTEPS)
step = 0;
// store
self.step = step;
// time duration until next step
time = [time dateByAddingTimeInterval:0.2];
}
所以每步之间的时间是0.2秒。我试图在视图控制器.m中实现这样的速度滑块(滑块的范围为0.3到1.0,因此将输出与当前时间类似的值):
- (IBAction)sliderMoved:(UISlider *)sender
{
AppDelegate* app = [[UIApplication sharedApplication] delegate];
app.tempo = sender.value;
}
并将while(self.running)线程中的行更改为:
time = [time dateByAddingTimeInterval: (NSTimeInterval) _tempo];
但是,这会导致步骤之间的时间太短(速度很快),当触摸应用程序中的任何控件时,它会崩溃。
我想知道是否需要设置这样的功能,但我不确定内部会有什么能使速度滑块工作:
- (void)setTempo:(float)tempo
{
}
我试图尽可能清楚,如果有人能帮助我,我将非常感激,提前谢谢
答案 0 :(得分:1)
-(void) startDrumTick{
[self.myDrumTimer invalidate]; // stop any current existing timer
// perform the call to the method 'drumMethodOperation:'
// every 0.2 sec. NB: drumMethodOperation will run on main thread.
// this means that if you expect to do long-blocking operation,
// you will need to move that op to an async thread, in order to avoid
// the UI blocking
self.myDrumTimer = [NSTimer scheduledTimerWithTimeInterval:0.2
target:self
selector:@selector(drumMethodOperation:)
userInfo:nil
repeats:YES];
}
-(void)drumMethodOperation:(id)sender
{
// update step
int step = self.step + 1;
// wrap around if we reached NUMSTEPS
if (step >= NUMSTEPS)
step = 0;
// store
self.step = step;
// any other needed operation to run every 0.2 secs
}
下面是使用GCD进行异步线程管理的示例
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
// Long blocking operation ( DO NOT PERFORM ANY UI OPERATION, like changing a text label, setting an image to an UIImageView, etc. )
[self myLongDbQuery];
dispatch_async(dispatch_get_main_queue(), ^(void){
//Perform you UI Updates here
self.myLabel.text = @"Query done!!!";
});
});
希望有所帮助
答案 1 :(得分:1)
Luca对使用GCD是正确的。如果谈谈你的初步解决方案。 你为_tempo设定了初始值吗?看起来你的bug最初可能是由_tempo = 0引起的。如您所知,只有在一些用户操作后才会调用sliderMoved,因此您需要设置初始值。