核心动画,self.presentationLayer()是零

时间:2015-04-21 15:03:05

标签: swift core-animation

我有一个快速的自定义CALayer,它有一些动态(实际@NSManaged属性)我已正确设置所有内容并且正在调用图层actionForKey。

override public func actionForKey(key: String!) -> CAAction! {
    switch key {
    case "maxCircles", "numCircles":
        let animation = CABasicAnimation(keyPath: key)
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear);
        animation.fromValue = self.presentationLayer().valueForKey(key);
        animation.duration = 0.2
        return animation;
    default:
        return super.actionForKey(key)
    }
}

有时self.presentationLayer().会抛出异常,因为它是隐式展开的,并且是nil。在Objective-C中,代码通常只是:

[[self presentationLayer] valueForKey:key]

哪个没有崩溃,但我从未意识到它可以调用nil并生成0 - 这对我来说感觉非常错误。我无法保证我的动画来自无。

在Swift中访问presentationLayer的正确方法是什么?我应该测试零吗?即:

override public func actionForKey(key: String!) -> CAAction! {
    if ( key == "maxCircles" || key == "numCircles" ) && self.presentationLayer() != nil {

        let animation = CABasicAnimation(keyPath: key)
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear);
        animation.fromValue = self.presentationLayer().valueForKey(key);
        animation.duration = 0.2
        return animation;
    }
    return super.actionForKey(key)
}

2 个答案:

答案 0 :(得分:1)

presentationLayer属性返回一个可选项,所以是的,你应该测试nil。在Objective-C消息传递中,nil是一个无操作,因此不会导致您的应用程序崩溃。请记住,安全是swift的主要目标之一,因此您需要在此处进行自己的检查。如果你编写这样的函数,它的工作方式与Objective-C相似:

override public func actionForKey(key: String!) -> CAAction! {
    if key == "maxCircles" || key == "numCircles" {
        // Check your presentation layer first before doing anything else
        if let presoLayer = self.presentationLayer() as? CALayer {
            let animation = CABasicAnimation(keyPath: key)
            animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear);
            animation.fromValue = presoLayer.valueForKey(key);
            animation.duration = 0.2
            return animation;
        }
    }
    return super.actionForKey(key)
}

我假设您的其余代码就在这里,只是回答有关presentationLayer可选性的部分。我将您的switch切换为if,因为它对我来说似乎更具可读性。

答案 1 :(得分:1)

Matt Long的解决方案有效。但是,如果您希望保留switch语法,则可以使用nil语法测试case … where

override func actionForKey(key: String!) -> CAAction! {
    switch key {
    case "maxCircles", "numCircles" where self.presentationLayer() != nil:
        let animation = CABasicAnimation(keyPath: key)
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear);
        animation.fromValue = self.presentationLayer().valueForKey(key);
        animation.duration = 0.2
        return animation;
    default:
        return super.actionForKey(key)
    }
}

或者,如果没有表示层,您可以提供默认fromValue

animation.fromValue = self.presentationLayer() != nil ? self.presentationLayer().valueForKey(key) : 0;