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

Swift逆向循环异常:闭包内代码为何正向执行?

Swift代码执行顺序问题分析与解决

问题代码

fileprivate func genericNodeWalker(_ direction:Follow, encapsulatedMethod: @escaping (_ iNode:Int) -> Void) {
    switch direction {
    case .forwards:
        for nodeIndex in 0..<self.nodes.count {
            encapsulatedMethod(nodeIndex)
        }
    case .backwards:
        for indexNode in stride(from: self.nodes.count - 1, through: 0, by: -1) {
       // for nodeIndex in (0..<self.nodes.count).reversed() {
            print("indexNode \(indexNode)")
            encapsulatedMethod(indexNode)
        }
    }
}

fileprivate func fadeOutNodes2() {
    genericNodeWalker(.backwards) { index2D in
        let wait = SKAction.wait(forDuration: Double(index2D) * 2)
        let custom = SKAction.run {
            print("index2D \(index2D)")
        }
        let sequence = SKAction.sequence([wait,custom])
        self.nodes[index2D].run(sequence)
    }
}

问题现象

指定以逆向方式遍历节点时,控制台打印的indexNode是逆向顺序(6→0),但fadeOutNodes2闭包内SKAction.run里打印的index2D却是正向顺序(0→6);即使将循环改为正向执行,index2D的打印顺序依然是正向的。


错误原因

核心问题是闭包的执行时机和等待时长的逻辑不匹配:

  • 所有节点的SKAction是被同时添加并启动计时的,并非按遍历顺序依次执行。
  • 逆向遍历时,你给索引6的节点设置了6*2=12秒的等待,索引5是5*2=10秒,直到索引0是0秒等待。等待时间越短的节点会越早执行打印,所以最终顺序变成0→6,和遍历顺序完全相反。
  • 正向遍历的话,索引0等待0秒先执行,索引1等2秒后执行,自然还是0→6的顺序。

解决方法

方法1:调整等待时长的计算逻辑

让后遍历到的小索引节点等待更长时间,保证遍历顺序和执行顺序一致:

fileprivate func fadeOutNodes2() {
    genericNodeWalker(.backwards) { index2D in
        // 用节点总数减去当前索引,让大索引节点等待时间更短
        let wait = SKAction.wait(forDuration: Double(self.nodes.count - 1 - index2D) * 2)
        let custom = SKAction.run {
            print("index2D \(index2D)")
        }
        let sequence = SKAction.sequence([wait,custom])
        self.nodes[index2D].run(sequence)
    }
}

这样逆向遍历时,索引6的等待时长为0,会最先执行打印;索引5等待2秒后执行,以此类推,最终打印顺序就是6→0,和遍历顺序一致。

方法2:使用串行动作执行

如果不想依赖等待时长,可通过动作的完成回调实现严格串行执行:

fileprivate func fadeOutNodes2() {
    var previousAction: SKAction? = nil
    // 按逆向顺序遍历节点
    for indexNode in stride(from: self.nodes.count - 1, through: 0, by: -1) {
        let printAction = SKAction.run {
            print("index2D \(indexNode)")
        }
        if let prevAction = previousAction {
            // 当前动作在之前的动作完成后执行
            previousAction = SKAction.sequence([prevAction, printAction])
        } else {
            previousAction = printAction
        }
    }
    // 执行最终的串行动作序列
    previousAction.map { self.run($0) }
}

这种方式下,所有打印动作会严格按遍历顺序(6→0)依次执行,无需依赖等待时长,执行顺序更精准可控。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 23:27:49