2013-08-18 154 views
0

我试图在媒体播放器中设置一个“FastForward/Next”按钮,可以轻触移动到下一首歌曲或在当前歌曲中保持快进。大多数情况下,它的工作原理是:你可以成功地快速前进,并成功移动到下一首歌曲,但事实是,使它工作的NSTimer从不会失效,所以一旦开始快速前进,就永远不会停止。UIGestureRecognizer与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的答案,还是还有其他事情正在进行?

回答

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; 
} 
0

NSTimer需要选择应该取一个参数为NSTimer *,这里是从苹果公司的documentation

选择器的引用必须对应于返回void并接受一个参数的方法。计时器将自身作为参数传递给此方法。

试图改变自己的executeFastForward方法的签名是这样的:

-(void) executeFastForward:(NSTimer *)timer 

比你能无效作为参数传递的计时器,它实际上是烧制的计时器对象

+0

没有帮助。 :/但我确实得到了一个线索:在连接remoteControlReceivedWithEvent(使用相同的NSTimer方法完美工作)之后,我可以放心地说,它与启动整个事件的'UIGestureRecognizer'有关。任何想法为什么会搞乱'invalidate'方法? – Nerrolken