无法使用 animator() [ OSX ] 为 Swift 自定义属性设置动画

Posted

技术标签:

【中文标题】无法使用 animator() [ OSX ] 为 Swift 自定义属性设置动画【英文标题】:Unable to animate a Swift custom property with animator() [ OSX ] 【发布时间】:2016-02-24 12:51:59 【问题描述】:

我正在尝试使用 animator() 在 swift 中为 Objective-C 设置自定义属性的动画。但是当我尝试通过animator 设置属性时,我得到了EXC_BAD_ACCESS 异常。在之前的一个用 Objective-C 编写的应用程序中,我使用了相同的想法,并且成功了。

这是 Swift 中的类:

import Cocoa
import QuartzCore


@IBDesignable
class StopPlayButton: NSView 

    //This is the property that I am trying to animate
    @IBInspectable
    var playButtonShapeInterval:Float = 1.0 
        didSet
            self.needsDisplay = true
        
    

    @IBInspectable
    var isPressed:Bool = false
        didSet
            self.needsDisplay = true
        
    
    override func drawRect(dirtyRect: NSRect) 
        super.drawRect(dirtyRect)
        StyleKit.drawPlayStopButton(playButtonShapeInterval: CGFloat(self.playButtonShapeInterval), buttonPressed: self.isPressed)
    

    func toggle()
        NSAnimationContext.beginGrouping()
        NSAnimationContext.currentContext().duration = 1.0;
        NSAnimationContext.currentContext().timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut);
        if self.playButtonShapeInterval == 0 
            self.animator().playButtonShapeInterval = 1.0
        
        else
            self.animator().playButtonShapeInterval = 0.0//exception happending here...
        
        NSAnimationContext.endGrouping()
    
    override static func defaultAnimationForKey(key: String) -> AnyObject?
        if key == "playButtonShapeInterval" 
            return CABasicAnimation()
        
        return super.defaultAnimationForKey(key)
    


注意,如果我将属性名称从playButtonShapeInterval 更改为alphaValue,那么alpha 动画就可以了。

下面是上面移植到Objective-C的代码,做我想做的。我不确定有什么不同:

//StopPlayButton.m
#import "StopPlayButton.h"
#import "StyleKit.h"
#import <QuartzCore/QuartzCore.h>

@implementation StopPlayButton

- (void)drawRect:(NSRect)dirtyRect 
    [super drawRect:dirtyRect];
    NSLog(@"This is the interval: %f", self.playButtonShapeInterval);
    [StyleKit drawPlayStopButtonWithPlayButtonShapeInterval:self.playButtonShapeInterval buttonPressed:self.playButtonPressed];


-(void)setPlayButtonShapeInterval:(float)playButtonShapeInterval
    if(playButtonShapeInterval != _playButtonShapeInterval)
        _playButtonShapeInterval = playButtonShapeInterval;
        [self setNeedsDisplay:YES];
    


-(void)toggle
    [NSAnimationContext beginGrouping];
    [[NSAnimationContext currentContext] setDuration:0.5];
    [[NSAnimationContext currentContext] setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
    if(self.playButtonShapeInterval == 0)
        self.animator.playButtonShapeInterval = 1;
    
    else
        self.animator.playButtonShapeInterval = 0;
    
    [NSAnimationContext endGrouping];


+(id)defaultAnimationForKey:(NSString *)key
    if ([key isEqualToString:@"playButtonShapeInterval"]) 
        return [CABasicAnimation animation];
    
    return [super defaultAnimationForKey:key];


@end

//StopPlayButton.h
#import <Cocoa/Cocoa.h>

@interface StopPlayButton : NSView

@property (nonatomic) BOOL playButtonPressed;
@property (nonatomic) float playButtonShapeInterval;

-(void)toggle;

@end

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,并通过将自定义属性声明为“动态”来修复它。我相信这是 KVO 要求的。

dynamic var playButtonShapeInterval:Float = 1.0 
    didSet
        self.needsDisplay = true
    

【讨论】:

这仍然会导致我的机器上执行错误 我发现这篇文章对我 5 年后实现这一目标很有帮助:medium.com/better-programming/…【参考方案2】:

在 Swift 5 中,你需要这个:

@objc class YourView: NSClipView 
    @objc dynamic var yourAnimatableProperty = CGFloat(1)

    override static func defaultAnimation(forKey key: NSAnimatablePropertyKey) -> Any? 
        if key == "yourAnimatableProperty" 
            return CABasicAnimation()
        
        return super.defaultAnimation(forKey: key)
    

...

【讨论】:

以上是关于无法使用 animator() [ OSX ] 为 Swift 自定义属性设置动画的主要内容,如果未能解决你的问题,请参考以下文章

求大神解惑 unity3D animation 与 animator的问题

Animator.SetTrigger没有在多人游戏中调用

为 OSX 编写和公证可执行文件

OSX:Chrome 无法连接到 .localhost-domains。拒绝连接

Rigidbody和Animator的影响测试

无法在 Mac OSX 上启动 picoe/eto 应用程序