NSTextField 的摇动动画

Shake animation for NSTextField

基于关于 UIView 和 UITextField 摇动动画的类似问题,我已经实现了应该适用于 NSTextFields 的代码。但是动画永远不会运行。这里有什么问题?

NSRect textFieldFrame = [textfield frame];

CGFloat centerX = textFieldFrame.origin.x;
CGFloat centerY = textFieldFrame.origin.y;

CABasicAnimation *animation = [[CABasicAnimation alloc] init];
animation.keyPath = @"position";
animation.duration = 0.07;
animation.repeatCount = 4;
animation.autoreverses = true;

NSPoint one = NSMakePoint(centerX-5, centerY);
NSPoint two = NSMakePoint(centerX+5, centerY);

animation.fromValue = [NSValue valueWithPoint:one];
animation.toValue = [NSValue valueWithPoint:two];

[textfield.layer addAnimation:animation forKey:@"position"];

注意:[[textfield animator] setFrameOrigin:one]; 成功移动文本框

我最终使用循环 NSAnimationContext 动画组,每个动画组在完成时调用另一个。如果有更好的方法来做到这一点,我仍在寻找。但是万一其他人需要这个这是我的解决方案

NSRect textFieldFrame = [textfield frame];

CGFloat centerX = textFieldFrame.origin.x;
CGFloat centerY = textFieldFrame.origin.y;

NSPoint origin = NSMakePoint(centerX, centerY);
NSPoint one = NSMakePoint(centerX-5, centerY);
NSPoint two = NSMakePoint(centerX+5, centerY);


[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setCompletionHandler:^{

    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setCompletionHandler:^{


        [NSAnimationContext beginGrouping];
        [[NSAnimationContext currentContext] setCompletionHandler:^{

            [NSAnimationContext beginGrouping];
            [[NSAnimationContext currentContext] setCompletionHandler:^{

                [[NSAnimationContext currentContext] setDuration:0.0175];
                [[NSAnimationContext currentContext] setTimingFunction: [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut]];
                [[textfield animator] setFrameOrigin:origin];

            }];

            [[NSAnimationContext currentContext] setDuration:0.0175];
            [[NSAnimationContext currentContext] setTimingFunction: [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut]];
            [[textfield animator] setFrameOrigin:two];
            [NSAnimationContext endGrouping];

        }];

        [[NSAnimationContext currentContext] setDuration:0.0175];
        [[NSAnimationContext currentContext] setTimingFunction: [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut]];
        [[textfield animator] setFrameOrigin:one];
        [NSAnimationContext endGrouping];
    }];

    [[NSAnimationContext currentContext] setDuration:0.0175];
    [[NSAnimationContext currentContext] setTimingFunction: [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut]];
    [[textfield animator] setFrameOrigin:two];
    [NSAnimationContext endGrouping];

}];

[[NSAnimationContext currentContext] setDuration:0.0175];
[[NSAnimationContext currentContext] setTimingFunction: [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseOut]];
[[textfield animator] setFrameOrigin:one];
[NSAnimationContext endGrouping];