使用NSTimer的UIGestureRecognizer永不消亡

时间:2013-08-18 06:53:15

标签: ios uigesturerecognizer nstimer

我正在尝试在媒体播放器中设置“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是对汉兰达的回答,还是有其他事情发生?

2 个答案:

答案 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;
}