及时更新标签一次显示

Updating label in time shows up all at once

我有一个标签,我想用一些点填充,每个点按顺序出现,间隔 0.1 秒

func setUpDots(numberOfDots: Int) {
    for dots in 1...numberOfDots {
        DispatchQueue.global(qos: .userInteractive).async {
            DispatchQueue.main.async {
                self.setLabelToDots(numberOfDots: dots)
            }
            usleep(100000)      // wait 0.1 sec between showing each dot
        }
    }
}

func setLabelToDots(numberOfDots: Int) {
    let dots = Array( repeating: ".", count: numberOfDots).joined()
    myLabel.text = dots
    myLabel.setNeedsDisplay()
}

但所有的点都同时出现在标签上

我应该怎么做才能使点之间的指定延迟出现正确的效果?

感谢您的反馈。

基本上,您的 for-loop 正在做类似于...

for dots in 1...numberOfDots {
    self.setLabelToDots(numberOfDots: dots)
}

这是因为允许每个任务同时执行,而延迟对下一个任务何时执行没有影响运行。

您 "could" 使用串行队列或者您可以使用依赖操作队列,但更简单的解决方案可能是只使用 Timer

这将允许您在滴答之间设置 "delay" 并将计时器视为一种伪循环,例如

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var myLabel: UILabel!

    let numberOfDots = 10
    var dots = 0

    var timer: Timer?

    override func viewDidLoad() {
        super.viewDidLoad()
        myLabel.text = ""
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        guard timer == nil else {
            return
        }
        timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(tick), userInfo: nil, repeats: true)
    }

    @objc func tick() {
        dots += 1
        guard dots <= numberOfDots else {
            timer?.invalidate()
            timer = nil
            dots = 0
            return
        }
        numberOfDots(dots)
    }

    func numberOfDots(_ numberOfDots: Int) {
        // You could just use string consternation instead,
        // which would probably be quicker
        let dots = Array( repeating: ".", count: numberOfDots).joined()
        myLabel.text = dots
        myLabel.setNeedsDisplay()
    }
}

还有很多其他示例,但您也应该看看 documentation for Timer