Swift4中UIButton淡出动画扩展引发内存泄漏求助
我来帮你分析下这个内存泄漏的问题,以及对应的解决办法:
问题根源分析
你的内存泄漏主要来自两个不合理的操作:
- 动画未完成就强制修改按钮状态:你在调用
fadeOut()后立刻把按钮设为isHidden = true和isEnabled = false,此时Core Animation的动画还在后台执行,动画对象会持续持有按钮的layer,而按钮状态被强制修改后,系统无法正确触发资源释放逻辑,导致内存无法回收。 - 动画状态与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
相关产品推荐
相关产品推荐

