能否利用DispatchQueue对游戏用户滑动触发的动画任务串行排队执行?
用DispatchQueue实现动画任务的串行排队执行
完全可以用DispatchQueue实现你要的串行任务排队,而且比自己写队列更省心。核心思路是用自定义串行队列管理所有滑动触发的动画任务,串行队列本身会按任务提交顺序依次执行,刚好匹配你“按滑动顺序串行执行动画”的需求。
具体实现步骤:
- 创建自定义串行队列
不用全局的.userInteractivity队列(它是并发队列,默认会同时执行多个任务,不符合串行要求),直接创建自己的串行队列:
private let animationSerialQueue = DispatchQueue(label: "com.yourgame.swipeAnimationQueue")
队列标签用你的游戏包名+功能名,方便调试时区分。
- 封装滑动触发的动画任务
每次用户滑动时,把动画逻辑封装成DispatchWorkItem提交到串行队列。注意:UI动画必须在主队列执行,所以任务内部要切回主队列,并且要等动画真正完成后再让队列执行下一个任务——这里用动画的completion回调保证任务等待动画结束,比硬等1秒更可靠。
示例代码:
// 处理滑动事件的方法 func onUserSwipe(_ direction: SwipeDirection) { // 创建工作项 let animationWorkItem = DispatchWorkItem { [weak self] in guard let self = self else { return } // 用信号量等待动画完成 let semaphore = DispatchSemaphore(value: 0) // 切回主队列执行动画 DispatchQueue.main.async { self.playScreenAnimation(for: direction) { // 动画完成后发送信号,让工作项结束 semaphore.signal() } } // 等待动画完成,再让队列执行下一个任务 semaphore.wait() } // 把工作项提交到串行队列 animationSerialQueue.async(execute: animationWorkItem) } // 具体的动画执行方法,带完成回调 func playScreenAnimation(for direction: SwipeDirection, completion: @escaping () -> Void) { // 根据方向设置动画目标状态 let targetTransform: CGAffineTransform switch direction { case .left: targetTransform = CGAffineTransform(translationX: -UIScreen.main.bounds.width, y: 0) case .right: targetTransform = CGAffineTransform(translationX: UIScreen.main.bounds.width, y: 0) case .up: targetTransform = CGAffineTransform(translationX: 0, y: -UIScreen.main.bounds.height) case .down: targetTransform = CGAffineTransform(translationX: 0, y: UIScreen.main.bounds.height) } // 执行1秒动画,完成后重置状态并调用回调 UIView.animate(withDuration: 1.0, animations: { self.screenContainerView.transform = targetTransform }) { _ in self.screenContainerView.transform = .identity completion() } }
为什么不用DispatchGroup?
DispatchGroup主要用于等待一组并发任务全部完成,而你需要的是任务按顺序串行执行,串行队列本身就天然支持这个逻辑,所以DispatchGroup在这里不是必需的——除非你需要在所有排队的动画都完成后执行某个统一操作,才需要结合DispatchGroup。
关键注意点:
- 用
[weak self]避免循环引用,防止内存泄漏。 - 必须依赖动画的
completion回调触发信号量,不要用Thread.sleep(forTimeInterval: 1)硬等,系统负载可能导致动画实际耗时波动,硬等会出现任务不同步的问题。 - 串行队列会严格按照用户滑动的顺序执行每个动画任务,完全满足你“记录所有滑动触发的函数,按完成顺序串行执行”的需求。
内容的提问来源于stack exchange,提问作者rayaantaneja
相关产品推荐
相关产品推荐

