【问题标题】:GCD Timer repeats firing on dispatch_suspendGCD 计时器在 dispatch_suspend 上重复触发
【发布时间】:2014-12-04 01:36:34
【问题描述】:

我使用 Xcode 5.1 和 Cocos2d v3.0 作为参考。在这个练习应用程序中,我希望用户按住屏幕。如果用户按住一秒钟,程序应该运行“someMethod”。用户在屏幕上按住的每一秒,程序都应该运行“someMethod”。因此,如果用户在屏幕上总共按住一秒钟的时间总共五秒钟,则应该调用“someMethod”。如果用户没有按住屏幕,则时间不应运行。我希望这在用户按住的每个计时器上都能正常工作。因此,如果用户按住一秒钟,将手指从屏幕上移开,然后再次按住,计时器应该会重置。最后,如果用户按住 2.5 秒,则不应第三次触发“someMethod”。

我的问题是,如果我从屏幕上抬起手指,我的重复计时器不会停止

这是我的输出示例

2014-12-03 19:47:45.987 Practice App[14739:f03] fire      
2014-12-03 19:47:46.986 Practice App[14739:f03] fire 
//after this point in time I am not holding down on the screen   
2014-12-03 19:47:47.986 Practice App[14739:f03] fire  
2014-12-03 19:47:48.986 Practice App[14739:f03] fire   
2014-12-03 19:47:49.986 Practice App[14739:f03] fire
@implementation GameScene
{
    dispatch_source_t dispatchSource;
}

- (instancetype)init
{

     if (self = [super init]){
    dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
                                                              dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));

    double interval = 1.0;
    dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, 0);
    uint64_t intervalTime = (int64_t)(interval * NSEC_PER_SEC);
    dispatch_source_set_timer(dispatchSource, startTime, intervalTime, 0);

    dispatch_source_set_event_handler(dispatchSource, ^{
        [self someMethod];
    });


  ...
  }
  return self;
}

- (void)fixedUpdate:(CCTime)dt
{
    if(touchState == kTouchDown){//The player is touching the screen
        dispatch_resume(dispatchSource);
    }

    if (touchState == kTouchUp) {//The player isn't touching the screen
        dispatch_suspend(dispatchSource);
    }
}

- (void)someMethod{
    NSLog(@"fire");
}

【问题讨论】:

  • 在 Cocos2D 中不要使用 GCD 来计时。下面解释了这个问题,虽然这个答案是关于 Sprite Kit 它同样适用于 Cocos2D:stackoverflow.com/a/23978854/201863 此外,如果你在 cocos2d 中使用动作或调度方法,创建计时器会简单得多。只需查看设置 GCD 计时器的所有代码,其中 CCNode 的调度方法是单行的。

标签: iphone timer cocos2d-iphone grand-central-dispatch


【解决方案1】:

使用 5 个长按手势识别器,一个会在 1 秒时触发,第二个会在 2 秒后触发,依此类推...,这里是第一个的示例,与其他人一起做并调整时间:

UILongPressGestureRecognizer* recognizerOneSec = 
        [[UILongPressGestureRecognizer alloc] 
                initWithTarget:self
                        action:@selector(handleLongPressFrom:)];
recognizer.minimumPressDuration = 1.0; // seconds
[[[CCDirector sharedDirector] view] 
        addGestureRecognizer:recognizer];

这将在 1 秒后触发:

-(void)handleLongPressFrom:(UILongPressGestureRecognizer*)recognizer
{
  //Perform here some logic to detect wich gesture will you handle
  //Example: if (recognizer is recognizerOneSec)

    if(recognizer.state == UIGestureRecognizerStateEnded)
    {
        CCLOG(@"Long press gesture recognized.");

        // Get the location of the touch in Cocos coordinates.
        CGPoint touchLocation = [recognizer locationInView:recognizer.view];

        //Do something with the touchLocation
    }
}

稍后,不要忘记这一点,您也可以在每次需要时尝试删除并重新创建手势:

-(void) onExit{
    NSArray *grs = [[[CCDirector sharedDirector] view] gestureRecognizers];

    for (UIGestureRecognizer *gesture in grs){
        if([gesture isKindOfClass:[UILongPressGestureRecognizer class]]){
            [[[CCDirector sharedDirector] view] removeGestureRecognizer:gesture];
        }
    }
}

我想到的另一种方法是创建一个类,带有一个挂起变量并引用该对象,以便您可以向它发送挂起消息,但您必须处理更多事情,例如可能的内存问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多