如何在闭包内创建闭包?Swift自定义重复动画闭包报错求助
自定义重复动画的问题修复方案
看你给出的代码片段,能发现几个导致完成闭包出错的核心问题,我一步步帮你梳理和修复:
1. 闭包类型定义错误
你定义的animationsVar和completionVar类型是(() -> ()?)?,这个类型和UIKit动画要求的闭包类型不匹配——系统动画的动画闭包是() -> Void,完成闭包还会额外传入一个Bool参数表示动画是否完成。类型不匹配是闭包报错的常见原因,应该修正为:
var animationsVar: (() -> Void)? var completionVar: ((Bool) -> Void)?
2. 尽量避免全局变量
你用了一堆全局变量存储动画参数,这很容易引发状态混乱,最好把参数封装在函数内部,用递归逻辑传递,避免全局状态带来的意外问题。
3. 完整的递归重复动画实现
下面是修正后的完整代码,用递归方式在完成闭包里触发下一次动画,完全不用系统的.repeat选项:
import UIKit func repeatingAnimation(withDuration duration: TimeInterval, options: UIViewAnimationOptions, numberOfIterations: Int, animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil) { // 内部递归函数,跟踪当前执行次数 func performAnimation(currentIteration: Int) { UIView.animate(withDuration: duration, delay: 0, options: options, animations: animations, completion: { finished in if currentIteration < numberOfIterations { // 未达到指定次数,继续执行下一次动画 performAnimation(currentIteration: currentIteration + 1) } else { // 所有重复执行完毕,调用最终完成闭包 completion?(finished) } }) } // 启动第一次动画 performAnimation(currentIteration: 1) }
4. 使用示例
比如让一个视图透明度反复切换3次,你可以这样调用:
let testView = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100)) testView.backgroundColor = .red UIApplication.shared.keyWindow?.addSubview(testView) repeatingAnimation(withDuration: 0.5, options: .curveEaseInOut, numberOfIterations: 3, animations: { testView.alpha = testView.alpha == 1 ? 0.5 : 1 }, completion: { finished in print("所有重复动画执行完毕!") })
关键说明
- 用内部递归函数跟踪执行次数,完全避免全局变量的干扰
- 严格匹配UIKit动画的闭包类型,特别是完成闭包的
Bool参数 - 可以精准控制重复次数,所有循环结束后才触发最终的完成回调,完全符合你自定义控制的需求
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

