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

时间:2015-11-22 10:19:27

标签: swift macos animator

我正在尝试使用swift中的animator()为Objective-C设置自定义属性的动画。但是当我尝试通过EXC_BAD_ACCESS设置属性时,我收到animator异常。在先前的一个用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)
    }

}

注意,如果我将属性名称更改为playButtonShapeIntervalalphaValue,则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

2 个答案:

答案 0 :(得分:0)

我遇到了同样的问题并通过将自定义属性声明为动态&#39;来修复它。我相信KVO要求它。

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

答案 1 :(得分:0)

在 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)
    }

... }