0

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

4

2 回答 2

0

好吧,经过大量的实验(并且受到这个无关但类似问题的答案if中的陈述的启发),我终于找到了一个解决方案:不要检查方法中手势的结束,而是检查方法。此外,事实证明该方法被一遍又一遍地调用,重新创建了计时器,因此该语句还通过将计时器限制为.executeFastForwardstartFastForwardstartFastForwardifUIGestureRecognizerStateBegan

这是工作代码,适合任何想要它的人:

- (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;
}
于 2013-08-18T08:00:13.370 回答
0

NSTimer采用选择器,该选择器应采用一个参数作为,这是来自 Apple文档NSTimer *的引用

选择器必须对应于返回 void 并采用单个参数的方法。计时器将自己作为参数传递给此方法。

尝试像这样更改executeFastForward 方法的签名:

-(void) executeFastForward:(NSTimer *)timer

比您可以使作为参数传递的计时器无效,这实际上是触发的计时器对象

于 2013-08-18T07:01:39.663 回答