方法重新运行时,方法中的循环dispatch_after会导致许多同时调度

时间:2014-02-09 20:13:54

标签: ios objective-c grand-central-dispatch nsoperation

我正在制作一款简单的游戏。

我有以下代码:

- (void)doStuff
{
    double delayInSeconds = [NSNumber randomFloatBetweenLowerBound:0.8f upperBound:2.6f];    // Own category on NSNumber returns random float.
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        //
        //  Do stuff
        //

        if ([self shouldDoMoreStuff]) {
            [self doStuff];
        }
    });
}

此方法在viewDidLoad中运行,但也会在玩家死亡时(按“再试一次”后)运行。

在几次死亡之后,最终会同时运行此方法的多次迭代,而不仅仅是一次。

我对GCD和NSOperation等了解不多,但我很确定我应该使用某些东西来控制它 - 也许NSOperation - 所以在viewDidLoad它是运行,然后当播放器死亡时,我取消操作,然后重新启动它。

正如我所说,我对NSOperation了解不多,所以我不知道是不是: a)我应该使用什么 和b)我应该如何使用它。

任何人都可以提供一些关于如何实现这一目标的想法吗?

一如既往地谢谢。

2 个答案:

答案 0 :(得分:1)

由于您在一个线程上执行此操作(主队列位于主线程上),因此一个简单的标志就足够了。在排队之前检查它;如果它关闭,设置它并入队,否则跳过入队。 Block应该做的最后一件事就是关闭旗帜。

如果涉及多个线程,你需要一些设计用于线程间标记的东西,比如一个调度信号量,以指示一个Block已经入队。

答案 1 :(得分:-1)

我修改了代码,以便您不需要删除块并添加等。

在viewController的.h文件中添加

@property NSInteger currentCount;

为了您的理解和演示,我们假设我们在viewControllers视图上发生触摸时重试它。

在.m文件中

- (void)viewDidLoad
{
    [super viewDidLoad];
    _currentCount=0;
    [self doStuff:_currentCount];

}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    //player dead, now start it again
    _currentCount++;
    [self doStuff:_currentCount];
}

- (void)doStuff:(NSInteger)count
{
    NSLog(@"came top %d",count);
    double delayInSeconds = 2;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        if(count==self.currentCount){
            //
            //  Do stuff
            //

            if([self shouldDoMoreStuff]) {
                [self doStuff:count];
            }
        }
    });
}
-(BOOL)shouldDoMoreStuff{
    return YES;
}