如何强制在Swift中更新UI?

时间:2019-05-28 02:35:41

标签: multithreading user-interface swift3 thread-safety dispatch

我正在迅速开发国际象棋游戏。当计算机在自娱自乐时,直到移动完成循环(在这种情况下游戏结束)后,显示屏才会更新,直到移动完成。

我尝试将其分派到后台队列中以生成移动并将其分派回主队列以进行移动并更新显示。虽然这似乎有助于更新显示,但是我无法预测每个后台队列的完成情况。这弄乱了动作的顺序。

是否有更好的方法可以使计算机自动播放并在每次移动完成后正确更新显示?

while chessGame.checkmate != true {
    DispatchQueue.global(qos: .background).async {
        let bestMove = chessAI.findBestMove(depth : chessGame.searchDepth)
        if bestMove != nil {
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) {
                chessMove.makeMove(m : bestMove!)
                self.boardView.setNeedsDisplay()
            }
        } else {
            print("CheckMate!")
            chessGame.checkmate = true
        }
    }
}

1 个答案:

答案 0 :(得分:0)

可以立即强制显示(通过调用displayIfNeeded),但这无济于事。

问题在于while循环不会在两次迭代之间暂停:它只是使循环保持最高速度。因此,while循环是一个糟糕的策略。

请使用递归。这样可以控制何时进行下一次迭代,即在延迟后递归。这是一个循环,您需要在两次迭代之间暂停。

伪代码:

func nextMove() {
    DispatchQueue.global(qos: .background).async {
        let bestMove = chessAI.findBestMove(depth : chessGame.searchDepth)
        if bestMove != nil {
            DispatchQueue.main.asyncAfter(deadline: .now() + 3) { // or whatever
                chessMove.makeMove(m : bestMove!)
                self.boardView.setNeedsDisplay()
                if chessGame.checkmate != true {
                    nextMove()
                } else {
                    print("checkmate")
                }
            }
        }
    }
}