Search code examples
iosobjective-cswiftcabasicanimationcatransaction

CABasicAnimation not working all the time


I have the following code that is supposed to give the effect of the view "shaking" and then dismissing it by sliding up off of the screen.

Sometimes it presents perfectly, but most of the time the shake animation will not display and the view will just slide up. I can't figure out what the problem could be:

CABasicAnimation *animation =
        [CABasicAnimation animationWithKeyPath:@"position"];
        [animation setDuration:0.05];
        [animation setRepeatCount:8];
        [animation setAutoreverses:YES];
        [animation setFromValue:[NSValue valueWithCGPoint:
                                 CGPointMake([[self editView] center].x - 20.0f, [[self editView] center].y)]];
        [animation setToValue:[NSValue valueWithCGPoint:
                               CGPointMake([[self editView] center].x + 20.0f, [[self editView] center].y)]];
        [[[self editView] layer] addAnimation:animation forKey:@"position"];
        
        [CATransaction begin]; {
            [CATransaction setCompletionBlock:^{
                
                
                [UIView animateWithDuration:0.4f delay:0.7 options:UIViewAnimationOptionTransitionNone animations:^{
                    
                    _editView.center = CGPointMake(self.navigationController.view.bounds.size.width / 2, 0 - 380);
                    [_textView resignFirstResponder];
                    
                    [_tint setAlpha:0];
                    
                    
                } completion:^(BOOL finished) {
                    
                    [_editView removeFromSuperview];
                    [_tint removeFromSuperview];
                }];
                
            }];
            
} [CATransaction commit];

Solution

  • The only change you need to make is re-place:

    [[[self editView] layer] addAnimation:animation forKey:@"position"];
    

    to right above [CATransaction commit];.

    Thus, it becomes:

    [CATransaction begin];
    {
        [CATransaction setCompletionBlock:^
        {
            [UIView animateWithDuration:0.4f delay:0.7f options:UIViewAnimationOptionTransitionNone animations:^
            {
                _editView.center = CGPointMake(self.navigationController.view.bounds.size.width / 2.0f, -380.0f);
               [_textView resignFirstResponder];
               [_tint setAlpha:0];
            }
            completion:^(BOOL finished)
            {
                [_editView removeFromSuperview];
                [_tint removeFromSuperview];
            }];
        }];
    }
    [[[self editView] layer] addAnimation:animation forKey:@"position"];
    [CATransaction commit];
    

    Then, the shaking part will take place first before it begins to animate upward as you want it to.