如何使用延迟循环更新UI?

时间:2022-09-22 21:00:48

I'm writing a cricket simulator app. I want to implement a quick inning in a loop, until the team is all out. But I want a small delay after each ball so users can see the scoreboard updating.

我正在写一个板球模拟器应用程序。我希望在循环中实现快速局,直到团队全力以赴。但我想在每个球后稍微延迟,以便用户可以看到记分牌更新。

Here's a snippet of the code:

这是代码的片段:

        while (match.currentInnings == currentInnings)
        {
            playSingleBall()
            if (gameover == true)
            {
                return
            }
            // Here's where I want the delay
       }

playSingleBall does a ton of stuff including a lot of computation and then writing to lots of Labels in the view. However, if I put a delay where the comment is (usleep or something else), the labels don't update at all. Can you suggest anything that would make the labels update? Or a delay method that wouldn't have this problem?

playSingleBall做了大量的事情,包括大量的计算,然后在视图中写入大量的标签。但是,如果我将评论延迟(usleep或其他),标签根本不会更新。你能建议一些能让标签更新的东西吗?还是一种没有这个问题的延迟方法?

Thanks.

谢谢。

2 个解决方案

#1


1  

You can use the Timer class, with a repeating handler:

您可以使用Timer类,使用重复处理程序:

// Every 20 sceonds
let interval: TimeInterval = 20

Timer(timeInterval: interval, repeats: true) { (timer) in
    // Do what every you want to do (update the UI)

    // Stop the loop when the game is over
    if (gameover) {
        timer.invalidate()
    }
}

#2


0  

I would put playSingleBall inside an if statement controlled by another variable. This variable would be set to false at the very first line of playSingleBall, and would then be switched back to true whenever one of the logic flows of playSingledBall reaches it's end.

我将playSingleBall放在由另一个变量控制的if语句中。这个变量在playSingleBall的第一行被设置为false,然后只要playSingledBall的一个逻辑流到达它的末尾就会切换回true。

I'd also look at assigning playSingleBall to the mainqueue since it updates the UI.

我还会考虑将playSingleBall分配给mainqueue,因为它会更新UI。

Something like so:

像这样的东西:

var singleBallBlocker : Bool = true

func playSingleBall() {

   singleBallBlocker = false


   // run the method...

   // at some point.. wherever the function ends or returns you need to call:

   singleBallBlocker = true

}

And your code above wherever you might be using it:

以及您在以下任何地方使用它的代码:

while (match.currentInnings == currentInnings)
        {
            if singleBallBlocker 
            {
                DispatchQueue.main.async(execute: {
                   playSingleBall()
                }
            }
            if (gameover == true)
            {
                return
            }
            // Here's where I want the delay
       }

Of course if you dont need the blocker to be reset inside the method, then just have it reset wherever you see fit.

当然,如果您不需要在方法中重置阻止程序,那么只需将其重置为您认为合适的位置。

#1


1  

You can use the Timer class, with a repeating handler:

您可以使用Timer类,使用重复处理程序:

// Every 20 sceonds
let interval: TimeInterval = 20

Timer(timeInterval: interval, repeats: true) { (timer) in
    // Do what every you want to do (update the UI)

    // Stop the loop when the game is over
    if (gameover) {
        timer.invalidate()
    }
}

#2


0  

I would put playSingleBall inside an if statement controlled by another variable. This variable would be set to false at the very first line of playSingleBall, and would then be switched back to true whenever one of the logic flows of playSingledBall reaches it's end.

我将playSingleBall放在由另一个变量控制的if语句中。这个变量在playSingleBall的第一行被设置为false,然后只要playSingledBall的一个逻辑流到达它的末尾就会切换回true。

I'd also look at assigning playSingleBall to the mainqueue since it updates the UI.

我还会考虑将playSingleBall分配给mainqueue,因为它会更新UI。

Something like so:

像这样的东西:

var singleBallBlocker : Bool = true

func playSingleBall() {

   singleBallBlocker = false


   // run the method...

   // at some point.. wherever the function ends or returns you need to call:

   singleBallBlocker = true

}

And your code above wherever you might be using it:

以及您在以下任何地方使用它的代码:

while (match.currentInnings == currentInnings)
        {
            if singleBallBlocker 
            {
                DispatchQueue.main.async(execute: {
                   playSingleBall()
                }
            }
            if (gameover == true)
            {
                return
            }
            // Here's where I want the delay
       }

Of course if you dont need the blocker to be reset inside the method, then just have it reset wherever you see fit.

当然,如果您不需要在方法中重置阻止程序,那么只需将其重置为您认为合适的位置。