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

能否利用DispatchQueue对游戏用户滑动触发的动画任务串行排队执行?

用DispatchQueue实现动画任务的串行排队执行

完全可以用DispatchQueue实现你要的串行任务排队,而且比自己写队列更省心。核心思路是用自定义串行队列管理所有滑动触发的动画任务,串行队列本身会按任务提交顺序依次执行,刚好匹配你“按滑动顺序串行执行动画”的需求。

具体实现步骤:

  1. 创建自定义串行队列
    不用全局的.userInteractivity队列(它是并发队列,默认会同时执行多个任务,不符合串行要求),直接创建自己的串行队列:
private let animationSerialQueue = DispatchQueue(label: "com.yourgame.swipeAnimationQueue")

队列标签用你的游戏包名+功能名,方便调试时区分。

  1. 封装滑动触发的动画任务
    每次用户滑动时,把动画逻辑封装成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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 12:43:40