I am trying to create a method which makes use of UIView's "+animateWithDuration:animations:completion" method to perform animations, and wait for completion. I am well aware that I could just place the code that would normally come after it in a completion block, but I would like to avoid this because there is a substantial amount of code after it including more animations, which would leave me with nested blocks.
I tried to implement this method as below using a semaphore, but I don't think this is the best way to do it, especially because it doesn't actually work. Can anyone tell me what is wrong with my code, and/or what the best way of achieving the same goal is?
+(void)animateAndWaitForCompletionWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations
{
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[UIView animateWithDuration:duration
animations:animations
completion:^(BOOL finished) {
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
I'm not sure what's wrong with my code but when I call the method as shown below, the completion block never runs and I end up in limbo.
[Foo animateAndWaitForCompletionWithDuration:0.5 animations:^{
//do stuff
}];
-------------------------------------------EDIT-------------------------------------------------
If anyone is facing a similar issue, you might be interested to see the code I used. It uses recursion to make use of each completion block, without having to nest each function call.
+(void)animateBlocks:(NSArray*)animations withDurations:(NSArray*)durations {
[Foo animateBlocks:animations withDurations:durations atIndex:0];
}
+(void)animateBlocks:(NSArray*)animations withDurations:(NSArray*)durations atIndex:(NSUInteger)i {
if (i < [animations count] && i < [durations count]) {
[UIView animateWithDuration:[(NSNumber*)durations[i] floatValue]
animations:(void(^)(void))animations[i]
completion:^(BOOL finished){
[Foo animateBlocks:animations withDurations:durations atIndex:i+1];
}];
}
}
which can be used like so
[Foo animateBlocks:@[^{/*first animation*/},
^{/*second animation*/}]
withDurations:@[[NSNumber numberWithFloat:2.0],
[NSNumber numberWithFloat:2.0]]];