2

我正在尝试使用animator()swift 为 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
4

2 回答 2

0

In Swift 5, you need this:

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

... }

于 2021-01-27T18:12:16.593 回答
0

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

dynamic var playButtonShapeInterval:Float = 1.0 {
    didSet{
        self.needsDisplay = true
    }
}
于 2016-04-11T04:03:02.733 回答