+ (void)pulseView:(UIView *)view completion:(void (^)(void))block { // if you use auto layout, view-based transform go haywire, as they trigger layoutSubviews // consequence is that you have no idea where the view will end up on the screen once animation completes // see this discussion: http://stackoverflow.com/questions/12943107/how-do-i-adjust-the-anchor-point-of-a-calayer-when-auto-layout-is-being-used // thus (per solution 4 from link above), rewriting with CAKeyframeAnimation CAKeyframeAnimation *ka = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; ka.duration = .49; ka.keyTimes = @[@(.102), @(.347), @(.551), @(.735), @(.898), @(1.0)]; ka.values = @[ [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(CGAffineTransformMakeScale(0.7, 0.7))], [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(CGAffineTransformMakeScale(1.25, 1.25))], [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(CGAffineTransformMakeScale(0.9, 0.9))], [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(CGAffineTransformMakeScale(1.05, 1.05))], [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(CGAffineTransformMakeScale(0.95, 0.95))], [NSValue valueWithCATransform3D:CATransform3DMakeAffineTransform(CGAffineTransformMakeScale(1.0, 1.0))] ]; ka.removedOnCompletion = YES; ka.repeatCount = 1; ka.fillMode = kCAFillModeForwards; ka.autoreverses = NO; if (block == NULL) { [view.layer addAnimation:ka forKey:@"transform"]; } else { [CATransaction begin]; [CATransaction setCompletionBlock:block]; [view.layer addAnimation:ka forKey:@"transform"]; [CATransaction commit]; } }