我正在尝试在媒体播放器中设置“FastForward / Next”按钮,可以轻触该按钮以移动到下一首歌曲或在当前歌曲中保持快进。大多数情况下,它可以工作:你可以成功地快速前进并成功地移动到下一首歌,但问题是,使它工作的NSTimer
永远不会失效,所以一旦你开始快速转发,你永远不会停止。
我在viewDidLoad
中设置了手势识别器:
UITapGestureRecognizer *singleTapFastForward = [[UITapGestureRecognizer alloc] initWithTarget: self action:@selector(nextSong:)];
singleTapFastForward.numberOfTapsRequired = 1;
[_buttonNext addGestureRecognizer:singleTapFastForward];
_holdFastForward = [[UILongPressGestureRecognizer alloc] initWithTarget: self action:@selector(startFastForward:)];
[_buttonNext addGestureRecognizer:_holdFastForward];
[singleTapFastForward requireGestureRecognizerToFail:_holdFastForward];
这是功能的核心:
- (IBAction)startFastForward:(id)sender {
_timerFastForward = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(executeFastForward) userInfo:nil repeats:YES];
}
- (void)executeFastForward {
[_avPlayer seekToTime:CMTimeMake(CMTimeGetSeconds([_avPlayer currentTime]) + 10, 1)];
if(_holdFastForward.state == 0) {
[self endFastForward:self];
}
}
- (IBAction)endFastForward:(id)sender {
[_timerFastForward invalidate];
}
这是一个棘手的部分:当我在if(_holdFastForward.state == 0)
行设置一个断点时,它会在我松开按钮后立即开始工作(应该如此),并成功调用endFastForward
方法。通过我的计算,这应该杀死计时器并结束整个周期,但然后再次调用executeFastForward
,然后一次又一次。 invalidate
行似乎什么都不做(我的代码中没有其他点可以调用executeFastForward
)。
有什么想法吗?这看起来很简单,如果invalidate
行有效,一切都会很完美。我只是不知道为什么继续调用executeFastForward
。我的NSTimer
TRON是对汉兰达的回答,还是有其他事情发生?
答案 0 :(得分:0)
NSTimer
需要将一个参数作为NSTimer *
的选择器,以下是来自Apple的documentation
选择器必须对应于返回void并接受单个参数的方法。计时器将自身作为此方法的参数传递。
尝试更改executeFastForward
方法的签名,如下所示:
-(void) executeFastForward:(NSTimer *)timer
可以使作为参数传递的计时器无效,这实际上是被触发的计时器对象
答案 1 :(得分:0)
好吧,经过大量的实验(并受到this answer if
声明中一个不相关但相似的问题的启发)我终于找到了一个解决方案:不要检查结束executeFastForward
方法中的手势,而是startFastForward
方法。此外,事实证明,startFastForward
方法被反复调用,重新创建计时器,因此if
语句也会通过将计时器限制为UIGestureRecognizerStateBegan
来停止。
这是适用于任何想要它的人的工作代码:
- (IBAction)startFastForward:(UIGestureRecognizer *)gestureRecognizer {
if(gestureRecognizer.state == UIGestureRecognizerStateBegan) {
_timerFastForward = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(executeFastForward) userInfo:nil repeats:YES];
} else if(gestureRecognizer.state == UIGestureRecognizerStateEnded) {
[self endFastForward:self];
}
}
- (void)executeFastForward {
[_avPlayer seekToTime:CMTimeMake(CMTimeGetSeconds([_avPlayer currentTime]) + 10, 1)];
}
- (IBAction)endFastForward:(id)sender {
[_timerFastForward invalidate];
_timerFastForward = nil;
}