Search code examples
iosiphoneobjective-cuikitcore-animation

Animation is delayed before starting


I am using code taken from another answer here but essentially below is what I am using. The main problem with this is that when I call it it takes 15 seconds to start then takes 15 seconds to complete each animation. I want it to start straight away! What am I missing here?

Called using

-(void)viewDidLoad {
    [self animationLoop: nil finished:nil context:nil];
}

Function

-(void)animationLoop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:15];

    int padding = _Circle1Container.frame.size.width / 2;

    // Circle 1
    CGFloat x = (CGFloat) (arc4random() % (int) self.view.bounds.size.width + padding);
    CGFloat y = (CGFloat) (arc4random() % (int) self.view.bounds.size.height + padding);

    CGPoint squarePostion = CGPointMake(x, y);
    _Circle1Container.center = squarePostion;
    [UIView setAnimationDelegate:self]; // as suggested by @Carl Veazey in a comment
    [UIView setAnimationDidStopSelector:@selector(animationLoop:finished:context:)];

    [UIView commitAnimations];
}

Solution

  • First of all, you should rename your _Circle1Container to _circle1Container, as capital letters are usually reserved for Class names.

    Second, use an animation block to perform your animation, as they are easier to read, and work better. Something like:

    int padding = _circle1Container.frame.size.width / 2;
    
    // Circle 1
    CGFloat x = (CGFloat) (arc4random() % (int) self.view.bounds.size.width + padding);
    CGFloat y = (CGFloat) (arc4random() % (int) self.view.bounds.size.height + padding);
    
    [UIView animateWithDuration:15.0f
                          delay:0.0f
                        options:UIViewAnimationOptionCurveLinear
                     animations:^{
                       _circle1Container.center = CGPointMake(x, y);
                     }
                     completion:^(BOOL finished){
                       // Fire a completion method here!
                     }];
    

    That way, you don't need to pass in all of those other parameters either.

    Finally, I'm not sure what you are trying to achieve with your padding variable. The range you are generating is [padding, width+padding], and [padding, height+padding]. Seems to me like you would want [padding, width-padding], and [padding, height-padding]. If that's the case, simply try:

    #define CLAMP(X, A, B) ((X < A) ? A : ((X > B) ? B : X))
    
    CGFloat x = (CGFloat) (arc4random() % ((int)self.view.bounds.size.width));
    CGFloat y = (CGFloat) (arc4random() % ((int)self.view.bounds.size.height));
    x = CLAMP(x, (CGFloat)padding, (CGFloat)(self.view.bounds.size.width - padding));
    y = CLAMP(y, (CGFloat)padding, (CGFloat)(self.view.bounds.size.height - padding));
    

    Hope that Helps!