Search code examples
iosiphoneobjective-cblock

What is happening in this block queue?


I was searching for a way to queue animation blocks, and happened across this blog post: http://xibxor.com/2013/03/27/uiview-animation-without-nested-hell/

I can't get it to work, though...the scope of how to arrange those elements isn't clear. Also, what are those semicolons on lines 18, 25, and 32 doing? Can anyone explain how to use this?

EDIT: here is the code copied from the source:

NSMutableArray* animationBlocks = [NSMutableArray new];

typedef void(^animationBlock)(BOOL);

// getNextAnimation
// removes the first block in the queue and returns it
animationBlock (^getNextAnimation)() = ^{
    animationBlock block = animationBlocks.count ? (animationBlock)[animationBlocks objectAtIndex:0] : nil;
    if (block){
        [animationBlocks removeObjectAtIndex:0];
        return block;
    }else{
        return ^(BOOL finished){};
    }
};

//add a block to our queue
[animationBlocks addObject:^(BOOL finished){;
    [UIView animateWithDuration:1.0 animations:^{
        //...animation code...
    } completion: getNextAnimation()];
}];

//add a block to our queue
[animationBlocks addObject:^(BOOL finished){;
    [UIView animateWithDuration:1.0 animations:^{
        //...animation code...
    } completion: getNextAnimation()];
}];

//add a block to our queue
[animationBlocks addObject:^(BOOL finished){;
    [UIView animateWithDuration:1.0 animations:^{
        //...animation code...
    } completion: getNextAnimation()];
}];

//add a block to our queue
[animationBlocks addObject:^(BOOL finished){;
    NSLog(@"Multi-step Animation Complete!");
}];

// execute the first block in the queue
getNextAnimation()(YES);

Solution

  • First thanks to share of this post, it's a great idea. That works perfectly for me:

    in your .h outside @interface:

    typedef void(^animationBlock)(BOOL);
    

    Then in your .m (here it's inside - (void)viewDidLoad):

    NSMutableArray* animationBlocks = [NSMutableArray new];
    
    UILabel* labelTest = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 50)];
    labelTest.text = @"Label Test";
    
    [self.view addSubview:labelTest];
    
    // getNextAnimation
    // removes the first block in the queue and returns it
    animationBlock (^getNextAnimation)() = ^{
        animationBlock block = animationBlocks.count ? (animationBlock)[animationBlocks objectAtIndex:0] : nil;
        if (block){
            [animationBlocks removeObjectAtIndex:0];
            return block;
        }else{
            return ^(BOOL finished){};
        }
    };
    
    //add a block to our queue
    [animationBlocks addObject:^(BOOL finished){;
        [UIView animateWithDuration:2.0 animations:^{
            NSLog(@"1-step Animation Complete!");
            labelTest.alpha = 0;
        } completion: getNextAnimation()];
    }];
    
    //add a block to our queue
    [animationBlocks addObject:^(BOOL finished){;
        [UIView animateWithDuration:2.0 animations:^{
            labelTest.text = @"New text";
        } completion: getNextAnimation()];
    }];
    
    //add a block to our queue
    [animationBlocks addObject:^(BOOL finished){;
        [UIView animateWithDuration:2.0 animations:^{
            labelTest.alpha = 1;
        } completion: getNextAnimation()];
    }];
    
    //add a block to our queue
    [animationBlocks addObject:^(BOOL finished){;
        NSLog(@"Multi-step Animation Complete!");
    }];
    
    // execute the first block in the queue
    getNextAnimation()(YES);
    

    It's a really simple animation but you need it to test it ^^

    Hope that will help.