Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dispatch_after versus performSelector afterDelay

I am writing a game with sliding blocks. In order to shuffle the game from the solved state, I would like to repeatedly call pushRandomPiece at regular interval to visually shuffle the game.

I wanted to use dispatch_after in the first place but I have a problem with the firing date:

This works:

-(void)shuffle {
    for (int i=0; i<50;i++)
    [self performSelector:@selector(pushRandomPiece) withObject:nil afterDelay:i*0.50*2];
}

The difference between two consecutive calls in pushRandomPiece is almost constantly equal to one second.

But this doesn't work:

-(void)shuffle {
    for (int i=0; i<50;i++)
//        [self performSelector:@selector(pushRandomPiece) withObject:nil afterDelay:i*0.50*2];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, i*NSEC_PER_SEC*0.5*2), dispatch_get_main_queue(), ^{ [self pushRandomPiece]; });
}

Here is the time difference between consecutive calls:

2013-10-01 11:02:53.147 SlidingPuzzle[2006:60b] diff= 1.077376
2013-10-01 11:02:54.262 SlidingPuzzle[2006:60b] diff= 1.111863
2013-10-01 11:02:55.335 SlidingPuzzle[2006:60b] diff= 1.070456
2013-10-01 11:02:56.455 SlidingPuzzle[2006:60b] diff= 1.117381
2013-10-01 11:02:57.542 SlidingPuzzle[2006:60b] diff= 1.084070
2013-10-01 11:02:58.655 SlidingPuzzle[2006:60b] diff= 1.110574
2013-10-01 11:02:59.757 SlidingPuzzle[2006:60b] diff= 1.098654
2013-10-01 11:03:00.862 SlidingPuzzle[2006:60b] diff= 1.103132
2013-10-01 11:03:01.956 SlidingPuzzle[2006:60b] diff= 1.091535
2013-10-01 11:03:03.050 SlidingPuzzle[2006:60b] diff= 1.090532
2013-10-01 11:03:04.160 SlidingPuzzle[2006:60b] diff= 1.107981
2013-10-01 11:03:04.164 SlidingPuzzle[2006:60b] diff= 0.000982
2013-10-01 11:03:06.354 SlidingPuzzle[2006:60b] diff= 2.187945
2013-10-01 11:03:06.357 SlidingPuzzle[2006:60b] diff= 0.000862
2013-10-01 11:03:08.498 SlidingPuzzle[2006:60b] diff= 2.139442
2013-10-01 11:03:08.501 SlidingPuzzle[2006:60b] diff= 0.000805
2013-10-01 11:03:10.750 SlidingPuzzle[2006:60b] diff= 2.246749
2013-10-01 11:03:10.753 SlidingPuzzle[2006:60b] diff= 0.000839

Here is the method that makes the blocks move:

-(void) pushRandomPiece {
    NSSet * s = [self freeBlocks];
    int n = [s count];
    int piece = arc4random_uniform(n);
    Piece * p = [[s allObjects] objectAtIndex:piece];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self pushPiece:p];
    });
}
like image 212
alecail Avatar asked Oct 01 '13 09:10

alecail


1 Answers

dispatch_after only adds your block to the queue after the time you have specified. If the queue is empty, your block may be run immediately upon being added to the queue. Otherwise, it may sit in the queue for some time before running -- waiting for other tasks to finish.

like image 191
justin Avatar answered Sep 18 '22 01:09

justin