如何在不中断主线程的情况下迅速延迟for循环? [英] How do I delay a for loop in swift without interrupting the main thread?

查看:59
本文介绍了如何在不中断主线程的情况下迅速延迟for循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通读一个字符的字符串,时间延迟.1秒,然后再继续下一个字符.

I am trying to read through a string one character a time delaying .1 seconds before moving on to the next character.

我尝试过在for循环中实现delay函数,但是它有两个问题.1.延迟不一致,并且在字符之间移动时所花费的时间不相同.2.它破坏了主线程,我认为这是导致相机视图冻结的原因.但是,我认为在相机开启时激活手电筒也有可能冻结信号,从而引起故障.

I have tried implementing the delay function inside the for loop but it has two problems. 1. The delay is inconsistent and does not take the same amount of time when moving between characters. 2. It disrupts the main thread which I think is the cause of the camera view freezing. However, I think it is also possible that activating the flashlight while the camera is on freezes the signal, causing the glitch.

func delay(_ delay:Double, closure:@escaping ()->()) {
    DispatchQueue.main.asyncAfter(
        deadline: DispatchTime.now () + Double(Int64(delay * 
    Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: 
    closure)
}

func scriptReader(){
    let str = "10101000001111110000110"
    for i in 0..<str.count {

        delay(Double(i) * 0.5) { 
            let index = str.index(str.startIndex, offsetBy:  i) 
            self.flash(number: str[index]) 
        }
    }
}
func flash(number: Character){
    guard let device = AVCaptureDevice.default(for: 
 AVMediaType.video) else { return }
    guard device.hasTorch else { return }

    if number == "0" {
        print("off")
        do {
            try device.lockForConfiguration()

            if (device.torchMode == AVCaptureDevice.TorchMode.on) {
                device.torchMode = AVCaptureDevice.TorchMode.off
            }
            device.unlockForConfiguration()
        } catch {
            print(error)
        }
    }

    if number == "1"{
        print("on")
        do {
            try device.lockForConfiguration()

            if (device.torchMode == AVCaptureDevice.TorchMode.off) {
                do {
                    try device.setTorchModeOn(level: 1.0)
                } catch {
                    print(error)
                }
            }
            device.unlockForConfiguration()
        } catch {
            print(error)
        }
    }
}

推荐答案

首先要担心的是,使用一系列 asyncAfter 会遇到计时器合并"的问题,操作系统将将来,单独调度的计时器可以一次全部触发,以充分利用设备电池(操作系统唤醒设备的次数越少,电池寿命就越长).排定的计时器越远,操作系统将进行的合并就越多.

Re your first concern, the use of a series of asyncAfter are going to suffer from "timer coalescing", where the OS will group future, individually scheduled timers to fire all at once, to make best use of the device battery (the less often the OS needs to wake up the device, the better the battery life). The further out the scheduled timers are, the more coalescing the OS will do.

可以通过重复使用 Timer 来避免这种情况:

One can avoid this by using a repeating Timer:

func handle(string: String) {
    guard !string.isEmpty else { return }

    var index = string.startIndex
    Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { timer in
        if string[index] == "0" {
            // handle "0"
        } else {
            // handle not "0"
        }

        index = string.index(after: index)
        if index == string.endIndex  { timer.invalidate() }
    }
}

这篇关于如何在不中断主线程的情况下迅速延迟for循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆