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

Swift4中UIButton淡出动画扩展引发内存泄漏求助

我来帮你分析下这个内存泄漏的问题,以及对应的解决办法:

问题根源分析

你的内存泄漏主要来自两个不合理的操作:

  1. 动画未完成就强制修改按钮状态:你在调用fadeOut()后立刻把按钮设为isHidden = true和isEnabled = false,此时Core Animation的动画还在后台执行,动画对象会持续持有按钮的layer,而按钮状态被强制修改后,系统无法正确触发资源释放逻辑,导致内存无法回收。
  2. 动画状态与layer实际值不一致:你只做了视觉上的淡出动画,但没有同步更新layer的实际opacity值,加上isRemovedOnCompletion = true的设置,动画结束后layer会自动恢复到原来的opacity(1),这种状态不一致也可能引发内存管理异常。

修复后的代码

我们需要调整动画逻辑,确保动画完成后再修改按钮状态,同时同步layer的实际属性值,让系统能正确回收资源:

修改后的UIButton扩展

extension UIButton {
    func fadeOut(completion: (() -> Void)? = nil) {
        // 先设置layer的最终opacity值,避免动画结束后跳回原状态
        self.layer.opacity = 0.0
        
        let fadeOut = CABasicAnimation(keyPath: "opacity")
        fadeOut.duration = 0.35
        fadeOut.fromValue = 1
        fadeOut.toValue = 0.0
        fadeOut.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
        fadeOut.autoreverses = false
        fadeOut.repeatCount = 0
        // 设置fillMode让动画结束后保持目标状态
        fadeOut.fillMode = .forwards
        // 配合fillMode,暂时不自动移除动画,后续手动清理
        fadeOut.isRemovedOnCompletion = false
        
        // 用CATransaction监听动画完成事件
        CATransaction.begin()
        CATransaction.setCompletionBlock {
            // 动画真正完成后再修改按钮状态
            self.isHidden = true
            self.isEnabled = false
            // 手动移除动画,释放资源
            self.layer.removeAnimation(forKey: "fadeOutAnimation")
            completion?()
        }
        // 给动画设置唯一key,方便精准移除
        self.layer.add(fadeOut, forKey: "fadeOutAnimation")
        CATransaction.commit()
    }
}

修改后的调用代码

private func menu_fadeout(){
    func menu_fadeout_helper(_ button:UIButton){
        button.fadeOut()
    }
    menu_fadeout_helper(hint)
    menu_fadeout_helper(new)
    menu_fadeout_helper(level)
    menu_fadeout_helper(card)
}

修复逻辑说明

  • 用fillMode = .forwards和isRemovedOnCompletion = false确保动画结束后保持淡出状态,避免layer属性跳变;
  • 通过CATransaction的完成回调,确保只有动画执行完毕后才修改按钮的隐藏和可用状态,避免动画运行时的资源持有冲突;
  • 给动画设置唯一key,后续手动移除动画对象,彻底释放相关内存。

这样调整后,你可以再用性能分析器检测,内存泄漏的问题应该就能解决了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:42:49