延迟循环(倒计时功能)

Delaying the loop (countdown func)

我看了很多文章,none 的答案是正确的。我知道这些方法有效,但在 for 循环中它们不起作用。我如何创建一个倒计时功能 - 我可以在其中打印一个数组,中间有一秒的延迟。

let array = [9, 8, 7, 6, 5, 4, 3, 2, 1]

我试过这个:

for n in array {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                print(n)
            }
        }

并在 1 秒后打印 所有数字。所以我尝试了这个:

override func viewDidLoad() {
    super.viewDidLoad()
let timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: (#selector(printer)), userInfo: nil, repeats: true)
}

@objc func printer() {
    for n in array {
       print(n)
        }
    }

同样的结果。我想这些都是很好的方法,但有些地方不对。

试试这个代码

let array = [9, 8, 7, 6, 5, 4, 3, 2, 1]

    DispatchQueue.global().async {
        for n in array {
            sleep(1)
            print(n)
        }  
    }

当你使用这个DispatchQueue是不正确的,因为它会被等待然后打印所有

为计时器创建一个计数器变量和另一个变量

var counter = 0
var timer : Timer?

viewDidLoad中创建定时器

override func viewDidLoad() {
    super.viewDidLoad()
    timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(printer), userInfo: nil, repeats: true)
}

在操作方法中增加 counter 变量并在达到数组中的项目数时使计时器无效。

@objc func printer() {

    print(array[counter])
    counter += 1
    if counter == array.count {
       timer?.invalidate()
       timer = nil
    }
}

另一种方法是DispatchSourceTimer,它避免了@objc运行时

var timer : DispatchSourceTimer?

let interval : DispatchTime = .now() + .seconds(1)

timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
timer!.schedule(deadline:interval, repeating: 1)
var index = 0
timer!.setEventHandler {
    // DispatchQueue.main.async {
       print(array[index])
    }
    index += 1
    if index == array.count {
        timer!.cancel()
        timer = nil
    }
}
timer!.resume()

For 循环几乎同时运行所有分派,因此所有分派都具有相同的等待时间,您可以像这样依赖它

let array = [9, 8, 7, 6, 5, 4, 3, 2, 1]
  for i in 0...array.count-1 {
    DispatchQueue.main.asyncAfter(deadline: .now() + Double(i) ) {
        print(array[i])
  }
}

我是这样倒计时的。不知道这样对不对,但确实有效

var timeRemaining: Int = 60

countdown()

func countdown() {
    if self.timeRemaining > 0 {
        DispatchQueue.main.asyncAfter(deadline: .now() + 1 ) {
            self.timeRemaining -= 1
            self.countdown()
        }
    }
}