无法使用 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的问题