You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确子类化CABasicAnimation添加自定义属性?解决初始化报错

解决子类化CABasicAnimation的初始化与回调问题

错误原因分析

你遇到的Use of unimplemented initializer 'init()'错误,是因为调用CustomCABasicAnimation()无参初始化方法时,自定义类未实现该初始化器——你仅定义了带callBack参数的初始化方法,而父类CABasicAnimation的无参初始化器不会被自动继承(自定义指定初始化器后,系统默认初始化器会失效)。

此外还有隐藏问题:CAAnimation添加到图层时会被系统拷贝(遵循NSCopying协议),若不处理拷贝逻辑,拷贝后的动画实例会丢失callBack属性,导致回调无法触发。

正确实现代码

1. 自定义CABasicAnimation子类

class CustomCABasicAnimation: CABasicAnimation, CAAnimationDelegate {
    // 将callBack设为可选类型,支持无参初始化后赋值
    var callBack: (() -> Void)?
    
    // 实现无参初始化器
    override init() {
        super.init()
        self.delegate = self
    }
    
    // 带回调参数的便捷初始化器(可选,支持直接创建时传入回调)
    convenience init(callBack: @escaping () -> Void) {
        self.init()
        self.callBack = callBack
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    // 重写拷贝方法,保证自定义属性被复制
    override func copy(with zone: NSZone? = nil) -> Any {
        let copy = super.copy(with: zone) as! CustomCABasicAnimation
        copy.callBack = self.callBack
        copy.delegate = copy // 拷贝后的实例需将代理设为自身
        return copy
    }
    
    // 实现动画停止回调逻辑
    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        guard flag else { return } // 仅在动画正常完成时触发回调
        callBack?()
    }
}

2. 调用示例(匹配你的目标结构)

extension NSView {
    func fadeAnimation(callBack: @escaping () -> Void) {
        let animation = CustomCABasicAnimation()
        animation.callBack = callBack
        
        // 配置动画参数
        animation.keyPath = "opacity"
        animation.duration = 2.0
        animation.fromValue = 1.0
        animation.toValue = 0.0
        animation.timingFunction = CAMediaTimingFunction(name: .linear)
        animation.isRemovedOnCompletion = false
        animation.fillMode = .forwards
        
        self.layer?.add(animation, forKey: nil)
    }
}

关键细节说明

  • 初始化器处理:实现override init()无参初始化器,同时将子类自身设为代理,确保回调能被正确触发;便捷初始化器为可选扩展,满足不同创建场景。
  • 拷贝逻辑:重写copy(with:)方法,手动复制callBack属性并绑定拷贝实例的代理,避免系统拷贝后丢失回调关联。
  • 回调触发时机:在animationDidStop中判断flag是否为true,仅在动画正常完成时执行回调,避免动画被提前终止时误触发。

内容的提问来源于stack exchange,提问作者swiftPunk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 18:55:27