【问题标题】:cancelPreviousPerformRequestsWithTarget is not workingcancelPreviousPerformRequestsWithTarget 不起作用
【发布时间】:2012-03-09 18:58:07
【问题描述】:

我在一个类中使用这个方法来启动一个动作:

[self performSelector:@selector(startRolling) withObject:nil afterDelay:0.1f];

为了阻止它,我正在使用:

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startRolling) object:nil];

但永远不会停止。

两个调用都在同一个类和同一个线程中实现。

这个我也用过,但是没解决:

-(void)stopRolling
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startRolling) object:nil];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(commitAnimation) object:nil];

    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:self];
}

我错过了什么?

谢谢。

---编辑---

要知道我正在使用的是否是主线程:

-(void)stopRolling
{
    if ([NSThread isMainThread])
        NSLog(@"Is Main Thread");

    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startRolling) object:nil];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(commitAnimation) object:nil];

    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:self];
}

什么时候工作正常,什么时候不总是出现在日志中是主线程。

我正在启动的选择器(startRolling 和 commitAnimations)是使用 [UIView beginAnimation:context:) 的动画

可能是这个原因吗?

方法如下:

-(void)startRolling
{
    currentPic++;

    if (currentPic > count)
        currentPic = 1;

    [UIView beginAnimations:@"fadeIn" context:nil];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:RDFadeInDelay];

    NSLog(@"RollUp: %@",[NSString stringWithFormat:@"RDInitialRollUp_%d",currentPic]);

    background.image = [UIImage imageNamed:[NSString stringWithFormat:@"RDInitialRollUp_%d.jpg",currentPic]];

    background.alpha = 1.0f;    

    [UIView commitAnimations];

}
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *) finished context:(void *) context
{
    if ([animationID isEqualToString:@"fadeIn"])
    {
        [self performSelector:@selector(commitAnimation) withObject:nil afterDelay:RDOnScreenDelay];
    }
    else
    {
        [self performSelector:@selector(startRolling) withObject:nil afterDelay:0.1f];

    }
}
-(void)commitAnimation
{
    [UIView beginAnimations:@"fadeOut" context:nil];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:RDFadeOutDelay];

    background.alpha = 0.0f;    

    [UIView commitAnimations];
}
-(void)stopRolling
{
    if ([NSThread isMainThread])
        NSLog(@"Is Main Thread");

    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startRolling) object:nil];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(commitAnimation) object:nil];

    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:self];
}

正在使用 performOnMainThread 调用调用 stopRolling 方法的方法:

谢谢。

---编辑---

我已经根据建议修改了方法,但仍然无法正常工作:

-(void)stopRolling
{
    if ([NSThread isMainThread])
        NSLog(@"Is Main Thread");
    else
        NSLog(@"Is NOT Main Thread");

    [self.layer removeAllAnimations];

    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startRolling) object:nil];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(commitAnimation) object:nil];

    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget:self];
}

我观察到,如果用户在执行图像之间的转换时点击屏幕,则当它不起作用时。但是如果用户在图像显示在屏幕上时(2 秒内)点击屏幕,一切正常。

始终在主线程上。

:(我绝望了,这让程序因为内存崩溃了。

--编辑--

最后我已经使用 BOOL 标志解决了。但我认为这是一个糟糕的解决方案,因为这必须在没有的情况下工作。正在执行动画时发生了一些奇怪的事情,因为这仅在动画未执行时才有效。

这适用于所有情况:

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *) finished context:(void *) context
{
    if (!mustAnimate) return;

    if ([animationID isEqualToString:@"fadeIn"])
    {
        [self performSelector:@selector(commitAnimation) withObject:nil afterDelay:RDOnScreenDelay];
    }
    else
    {
        [self performSelector:@selector(startRolling) withObject:nil afterDelay:0.1f];

    }
}
-(void)commitAnimation
{
    [UIView beginAnimations:@"fadeOut" context:nil];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:RDFadeOutDelay];

    background.alpha = 0.0f;    

    [UIView commitAnimations];
}
-(void)stopRolling
{
    mustAnimate = NO;

    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(startRolling) object:nil];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(commitAnimation) object:nil];

}

感谢一切。

【问题讨论】:

  • 你确定你检查了线程吗?它应该可以工作...设置更大的延迟以查看它是否工作如何?
  • 在几次测试中,我观察到有时会停止,有时不会。但最令人好奇的是,曾经做过同样的事情。我对这件事真的很迷茫。感谢您的回答。
  • 请确保您始终在同一个线程上...
  • 我已经编辑了有关该问题的更多详细信息。谢谢。
  • 所以,它总是发生在主线程上,并且您删除所有动画...当您观察它停止的时间时,您记录了时间吗?比如它实际发生的时间和它告诉它取消的时间?

标签: objective-c performselector


【解决方案1】:

更改传递给两个方法的参数,如图所示,

[self performSelector:@selector(SampleMethod) withObject:self afterDelay:delayTime];     
[NSObject cancelPreviousPerformRequestsWithTarget:self];       

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多